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-12-04 10:46:26

    nuxt.js项目中全局捕获异常并生成错误日志全过程

     需求:客户在使用过程中页面报错时,可以生成错误记录传回服务器,以便改进。   步骤:     一.全局捕获异常,     二.发送到服务端,     三.生成错误日志。   一.全局捕获异常 如图,vue提供了errorHandle这个方法来处理全局异常,更多详细内容参见官网。

  • 2019-12-04 10:47:59

    nuxt.js项目中全局捕获异常并生成错误日志全过程

     需求:客户在使用过程中页面报错时,可以生成错误记录传回服务器,以便改进。   步骤:     一.全局捕获异常,     二.发送到服务端,     三.生成错误日志。   一.全局捕获异常 如图,vue提供了errorHandle这个方法来处理全局异常,更多详细内容参见官网。

  • 2019-12-04 10:48:18

    vue 项目资源文件 static 和 assets 不说区别直接使用?

    assets中资源会webpack构建压缩到你代码中,而static文件直接引用。 static 中长存放类包、插件等第三方的文件,assets里放属资源文件比如自己资源图片、css文件、js文件。 引入资源的方式static文件夹可以使用~/static/方式引入, assets文件夹可以使用 ~@/assets 方式引入

  • 2019-12-05 17:01:36

    Vue 结合 Axios 接口超时统一处理

    当网路慢的时候。又或者公司服务器不在内地的时候,接口数据请求不回来超时报错的情况相信大家肯定遇到过的,这里我把我公司项目请求超时的处理方法分享下,希望看过后有帮助。

  • 2019-12-05 17:13:40

    JS模板工具lodash.template的简单用法

    lodash是从underscore分支的一个项目,之前我写了一篇JS模板工具underscore.template的简单用法,lodash跟underscore很相似,这也简单介绍一下lodash的template方法。 先把underscore的文章中用过的代码贴过来,把underscore的js文件换成lodash的js,其他一字不改,然后我们试试:

  • 2019-12-06 10:47:29

    date-fns日期工具的使用方法详解

    isToday() 判断传入日期是否为今天 isYesterday() 判断传入日期是否为昨天 isTomorrow() 判断传入日期是否为 format() 日期格式化 addDays() 获得当前日期之后的日期 addHours() 获得当前时间n小时之后的时间点 addMinutes() 获得当前时间n分钟之后的时间 addMonths() 获得当前月之后n个月的月份 subDays() 获得当前时间之前n天的时间 subHours() 获得当前时间之前n小时的时间 subMinutes() 获得当前时间之前n分钟的时间 subMonths() 获得当前时间之前n个月的时间 differenceInYears() 获得两个时间相差的年份 differenceInWeeks() 获得两个时间相差的周数 differenceInDays() 获得两个时间相差的天数 differenceInHours() 获得两个时间相差的小时数 differenceInMinutes() 获得两个时间相差的分钟数