put与putIfAbsent区别

2019-09-28 09:33:18

参考文章 put与putIfAbsent区别

put与putIfAbsent区别:

put在放入数据时,如果放入数据的key已经存在与Map中,最后放入的数据会覆盖之前存在的数据,

而putIfAbsent在放入数据时,如果存在重复的key,那么putIfAbsent不会放入值。


putIfAbsent   如果传入key对应的value已经存在,就返回存在的value,不进行替换。如果不存在,就添加key和value,返回null


底层实现:

public V put(K key, V value) { 
     if (value == null) 
          throw new NullPointerException(); 
     int hash = hash(key.hashCode()); 
     return segmentFor(hash).put(key, hash, value, false); } public V putIfAbsent(K key, V value) { 
     if (value == null) 
          throw new NullPointerException(); 
     int hash = hash(key.hashCode()); 
     return segmentFor(hash).put(key, hash, value, true); }

例子:

package com.xx;import java.util.HashMap;import java.util.Map;/**
 * JustForTest
 *
 * @create 2018-06-20 12:14
 */public class TestHan {

    public static void main(String[] args) {

        /**
         * put
         */
        Map<Integer,String> map = new HashMap<>();
        map.put(1,"ZhangSan");
        map.put(2,"LiSi");
        map.put(1,"WangWu");
        map.forEach((key,value) ->{
            System.out.println("key : " + key + " , value : " + value);
        });

        
        /**
         * putIfAbsent
         */
        Map<Integer,String> putIfAbsentMap = new HashMap<>();
        putIfAbsentMap.put(1,"张三");
        putIfAbsentMap.put(2,"李四");
        putIfAbsentMap.put(1,"王五");
        putIfAbsentMap.forEach((key,value) ->{
            System.out.println("key : " + key + " , value : " + value);
        });
    }}

            输出结果:

                

            key : 1 , value : WangWu

            key : 2 , value : LiSi

            key : 1 , value : 张三

            key : 2 , value : 李四

package com.xx;import com.alibaba.fastjson.JSON;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/**
 * JustForTest
 *
 * @create 2018-06-20 12:14
 */public class TestHan {

    /**
     * 处理重复数据与不重复数据,以重复数据为唯一,合并数据的方法。
     */
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student("张三", 1));
        list.add(new Student("李四", 1));
        list.add(new Student("王五", 2));
        list.add(new Student("赵六", 1));
        list.add(new Student("孙七", 2));
        list.add(new Student("周八", 1));
        list.add(new Student("吴九", 2));

        //对于上面的学生、如果根据班级进行区分?!
        Map<Integer,List<Student>> map = new HashMap<>();
        List<Student> students;
        for(Student s : list) {
            /**
             * put不管什么直接存入,返回旧值
             * putIfAbsent如果为null才存入,返回旧值。
             */
            students = map.putIfAbsent(s.getInClass(),new ArrayList<Student>(list.size()));
            if (null == students) {
                students = map.get(s.getInClass());
            }
            students.add(s);
        }

        //循环Map
        map.forEach((key,value) -> {
            System.out.println("班级:" + key + ",人员:" + JSON.toJSONString(value));
        });
    }}
package com.xx;/**
 * @author hanliwei
 * @create 2018-06-20 16:00
 */public class Student {
    private String name; //姓名
    private Integer inClass;//所属班级

    Student(String name,Integer inClass) {
        this.name = name;
        this.inClass = inClass;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getInClass() {
        return inClass;
    }

    public void setInClass(Integer inClass) {
        this.inClass = inClass;
    }}

------------------------------

Java8之Map的其他一些方法

------------------------------

Map<Integer,String> map = new HashMap<>();map.put(1,"a");map.put(2,"b");map.put(3,"c");
/**
 * 1.getOrDefault 方法
 *
 * 如果指定的key存在,则返回该key对应的value,
 * 如果不存在,则返回指定的值。
 *
 * 例子:key为4不存在,输出d
 */System.out.println(map.getOrDefault(4,"d"));

输出:d

/**
 * 2.forEach 方法
 *
 * 遍历Map中的所有Entry, 对key, value进行处理, 
    接收参数 (K, V) -> void,
 */map.forEach((key,value) -> System.out.println("key : " + key + " , value:" + value));

        输出:

        key : 1 , value:a

        key : 2 , value:b

        key : 3 , value:c

/**
 * 3.replaceAll 方法
 * 替换Map中所有Entry的value值,这个值由旧的key和value计算得出,
    接收参数 (K, V) -> V
 */map.replaceAll((key,value) -> ("new" + key) + value);map.forEach((key,value) -> System.out.println("key : " + key + " , value:" + value));

        输出:

        key : 1 , value:new1a

        key : 2 , value:new2b

        key : 3 , value:new3c

/**
 * 4.putIfAbsent 方法
 * 如果key关联的value不存在,则关联新的value值,返回key关联的旧的值
 */map.putIfAbsent(3, "d");map.putIfAbsent(4, "d");System.out.println(map.get(3));System.out.println(map.get(4));

    输出:

    c

    d

/**
 * 5.remove方法
 * 接收2个参数,key和value,如果key关联的value值与指定的value值相等(equals),则删除这个元素
 */map.remove(1,"b");System.out.println(map.get(1));//未删除成功,输出amap.remove(2,"b");System.out.println(map.get(2));//删除成功,输出null
/**
 * 6.replace(K key, V oldValue, V newValue) 方法
 * 如果key关联的值与指定的oldValue的值相等,则替换成新的newValue
 */map.replace(3,"a","z");System.out.println(map.get(3));//未替换成功,输出cmap.replace(1,"a","z");System.out.println(map.get(1));//替换成功,输出z
/**
 * 7.replace(K key, V value) 方法
 * 如果map中存在key,则替换成value值,否则返回null
 */// 输出旧的值, aSystem.out.println(map.replace(1, "aa"));// 替换成功,输出新的值, aaSystem.out.println(map.get(1));// 不存在key为4, 输出 nullSystem.out.println(map.replace(4, "d"));// 不存在key为4, 输出 nullSystem.out.println(map.get(4));
/**
 * 8.computeIfAbsent 方法
 * 如果指定的key不存在,则通过指定的K -> V计算出新的值设置为key的值
 */map.computeIfAbsent(1, key -> key + " computed");// 存在key为1,则不进行计算,输出值 aSystem.out.println(map.get(1));map.computeIfAbsent(4, key -> key + " computed");// 不存在key为4,则进行计算,输出值 4 computedSystem.out.println(map.get(4));
/**
 * 9.computeIfPresent 方法
 * 如果指定的key存在,则根据旧的key和value计算新的值newValue,
 * 如果newValue不为null,则设置key新的值为newValue,
 * 如果newValue为null, 则删除该key的值,
 */map.computeIfPresent(1, (key, value) -> (key + 1) + value);// 存在key为1, 则根据旧的key和value计算新的值,输出 2aSystem.out.println(map.get(1));map.computeIfPresent(2, (key, value) -> null);// 存在key为2, 根据旧的key和value计算得到null,删除该值,输出 nullSystem.out.println(map.get(2));


参考:

深入理解ConcurrentMap.putIfAbsent(key,value) 用法


  • 2019-08-20 11:22:36

    Node.js 单线程与多进程比较

    进过上面两种方式的对比,结果很明显,多进程处理速度是单线程处理速度的 4 倍多。而且有条件的情况下,如果电脑 CPU 足够,进程数更多,那么速度也会更快。

  • 2019-08-22 13:35:27

    Generator函数的语法

    执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了是状态机还是一个遍历器对象生成函数。 返回遍历器对象,可以依次遍历Generator函数内部的每一个状态。

  • 2019-08-22 16:38:15

    理解JS原型对象与原型链(重要清晰)

    JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象对应拥有一个原型,对象以其原型为模板、从原型继承方法和属性。而同时原型也是对象,它也拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。

  • 2019-08-22 17:26:21

    详解javaScript的深拷贝

    最开始意识到深拷贝的重要性是在我使用redux的时候(react + redux), redux的机制要求在reducer中必须返回一个新的对象,而不能对原来的对象做改动,事实上,当时我当然不会主动犯这个错误,但很多时候,一不小心可能就会修改了原来的对象,例如:var newObj = obj; newObj.xxx = xxx 实际上,这个时候newObj和obj两个引用指向的是同一个对象,我修改了newObj,实际上也就等同于修改了obj,这,就是我和深浅拷贝的第一次相遇。

  • 2019-08-22 19:14:21

    Android Studio 3.5最新特性

    Android Studio(以下简称为AS) 3.5正式版终于发布了,从第一个bate版本发布到正式版本,历时三个半月。AS一直以来被开发者吐槽,因此谷歌也放慢了版本的变化,对测试版本进行大力度的优化,提高了稳定性。从3.3版本开始,谷歌启动了名为Project Marble的计划,意为谷歌团队致力于使集成开发环境(IDE)的基本功能和流程变得坚如磐石,同时精炼和完善面向用户的功能。而AS 3.5则是Project Marble主要成果的版本,下面来介绍主要成果。

  • 2019-08-27 05:43:13

    Laravel 门面自动补全工具 laravel-ide-helper

    当我们在 PhpStorm 编辑器中,开发 Laravel 框架的项目时,很多类方法都不能自动补全和定位,比如 Facade 门面的方法,DB::table()、Route::get() 等。