首页 > 其他分享 >Map中经常被忽略但又非常好用的方法

Map中经常被忽略但又非常好用的方法

时间:2025-01-06 20:45:33浏览次数:6  
标签:Map hashMap oldValue value 忽略 User key null 好用

1. 简介

map是我们日常开发中常会的集合类之一, 但是我们除了常用的getput之外,其他的方法好像很少会用到,接下来我们就介绍一下几个经常被忽略但又很好用的方法.

2. Quick Start

2.1 数据准备

创建一个map对象, 并声明几个用于测试的user对象

Map<Integer, User> hashMap = Maps.newHashMap();
User zhangsan = new User(1, "张三");
User lisi = new User(2, "李四");
User zhangtieniu = new User(3, "张铁牛");

2.2 重温put

// hashmap put (添加/更新元素)
@Test
public void put() {
    User test = hashMap.put(null, null);
    User user = hashMap.put(1, null);
    User user1 = hashMap.put(1, zhangsan);
    User user2 = hashMap.put(1, lisi);
    User user3 = hashMap.put(null, zhangsan);
    User user4 = hashMap.put(null, lisi);
    User user5 = hashMap.get(null);
    log.info("map: {}", hashMap);
    log.info("user: {}, user1: {}, user2: {}, user3: {}, user4: {}, user5: {}", user, user1, user2, user3, user4, user5);
    //map: {null=User(id=2, name=李四), 1=User(id=2, name=李四)}
    //user: null, user1: null, user2: User(id=1, name=张三), user3: null, user4: User(id=1, name=张三), user5: User(id=2, name=李四)
}
  1. key和value可以为null (hashmap 和 linkedhashmap)
  2. 使用null可以正常的覆盖和获取元素
  3. put可以直接新增or覆盖已有的元素
  4. put方法返回对应key的oldValue,如果没有oldValue则返回null

2.3 getOrDefault

// getOrDefault(Object key, V defaultValue) (获取/返回默认值)
@Test
public void getOrDefault() {
    hashMap.put(1, zhangsan);
    hashMap.put(2, null);
    final User user1 = hashMap.get(1);
    final User user2 = hashMap.getOrDefault(2, lisi);
    final User user3 = hashMap.getOrDefault(3, zhangtieniu);
    log.info("map: {}", hashMap);
    //map: {1=User(id=1, name=张三), 2=null}
    log.info("user1: {}, user2: {}, user3: {}", user1, user2, user3);
    //user1: User(id=1, name=张三), user2: null, user3: User(id=3, name=张铁牛)
}
  1. 当map中没有对应的key时, 返回对应的defaultValue

    注意: 如果map中存在对应的key, 但是对应的value == null时, 返回的是null, 而不是defaultValue

源码如下:

default V getOrDefault(Object key, V defaultValue) {
    V v;
    return (((v = get(key)) != null) || containsKey(key))
        ? v
        : defaultValue;
}

2.4 putIfAbsent

// putIfAbsent(K key, V value) (如果不存在则添加)
@Test
public void putIfAbsent() {
    hashMap.put(1, null);
    User user1 = hashMap.putIfAbsent(1, zhangsan);
    User user2 = hashMap.putIfAbsent(2, lisi);
    User user3 = hashMap.putIfAbsent(2, zhangtieniu);
    log.info("map: {}", hashMap);
    log.info("user1: {}, user2: {}, user3: {}", user1, user2, user3);
    //map: {1=User(id=1, name=张三), 2=User(id=2, name=李四)}
    //user1: null, user2: null, user3: User(id=2, name=李四)
}
  1. 如果指定的key对应的value不为null时(oldValue != null) : 不覆盖 & 返回oldValue
  2. 当指定key的value不存在时(oldValue == null) : 添加元素 & 返回oldValue

可以理解为 当指定key的value不存在时, 才去put, 否则不添加

源码如下:

default V putIfAbsent(K key, V value) {
    V v = get(key);
    if (v == null) {
        v = put(key, value);
    }

    return v;
}

2.5 compute

// compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) (计算)
@Test
public void compute() {
    hashMap.put(1, zhangsan);
    User user1 = hashMap.compute(1, (k, oldValue) -> lisi);
    log.info("map: {}, user1: {}", hashMap, user1);
    //map: {1=User(id=2, name=李四)}, user1: User(id=2, name=李四)
    User user2 = hashMap.compute(1, (k, oldValue) -> null);
    log.info("map: {}, user2: {}", hashMap, user2);
    //map: {}, user2: null
}
  1. remappingFunction返回值 != null : 覆盖oldValue & 返回newValue
  2. remappingFunction返回值 == null : 删除对应元素 & 返回null

可以理解为 使用remappingFunction的返回值覆盖对应key的旧值, 当remappingFunction返回值为null时, 会直接将当前元素移除掉

源码如下:

default V compute(K key,
        BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
    Objects.requireNonNull(remappingFunction);
    V oldValue = get(key);

    V newValue = remappingFunction.apply(key, oldValue);
    if (newValue == null) {
        // delete mapping
        if (oldValue != null || containsKey(key)) {
            // something to remove
            remove(key);
            return null;
        } else {
            // nothing to do. Leave things as they were.
            return null;
        }
    } else {
        // add or replace old mapping
        put(key, newValue);
        return newValue;
    }
}

2.6 computeIfAbsent

// computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) (不存在则计算)
@Test
public void computeIfAbsent() {
    User user = hashMap.computeIfAbsent(1, k -> zhangsan);
    User user1 = hashMap.computeIfAbsent(1, k -> lisi);
    User user2 = hashMap.computeIfAbsent(2, k -> null);
    log.info("map: {}, user:{}, user1: {}, user2:{}", hashMap, user, user1, user2);
    //map: {1=User(id=1, name=张三)}, user:User(id=1, name=张三), user1: User(id=1, name=张三), user2:null
}
  1. oldValue != null : 不覆盖 & 返回oldValue
  2. oldValue == null && mappingFunction返回值 != null: 添加元素 & 返回newValue
  3. oldValue == null && mappingFunction返回值 == null: 不覆盖 & 返回oldValue

可以理解为 当指定key的value不存在时, 才使用mappingFunction的返回值覆盖对应key的旧值, 如果key对应value存在或者mappingFunction的返回值为null时, 则不覆盖

源码如下:

default V computeIfAbsent(K key,
        Function<? super K, ? extends V> mappingFunction) {
    Objects.requireNonNull(mappingFunction);
    V v;
    if ((v = get(key)) == null) {
        V newValue;
        if ((newValue = mappingFunction.apply(key)) != null) {
            put(key, newValue);
            return newValue;
        }
    }

    return v;
}

2.7 computeIfPresent

// computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) (存在则计算)
@Test
public void computeIfPresent() {
    hashMap.put(1, zhangsan);
    User user1 = hashMap.computeIfPresent(1, (k,oldValue) -> lisi);
    User user2 = hashMap.computeIfPresent(3, (k,oldValue) -> zhangtieniu);
    log.info("map: {}, user1: {}, user2: {}", hashMap, user1, user2);
    //map: {1=User(id=2, name=李四)}, user1: User(id=2, name=李四), user2: null
    User user3 = hashMap.computeIfPresent(1, (k,oldValue) -> null);
    log.info("map: {}, user3:{}", hashMap, user3);
    //map: {}, user3:null
}
  1. oldValue == null : 不覆盖&返回null
  2. oldValue != null && remappingFunction返回值 == null : 移除元素&返回null
  3. oldValue != null && remappingFunction返回值 != null : 覆盖元素&返回newValue

可以理解为 当key对应的value存在时, 才使用remappingFunction的返回值覆盖对应key的旧值, 如果key对应的value不存在或者remappingFunction的返回值为null时, 则不覆盖

源码如下:

default V computeIfPresent(K key,
        BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
    Objects.requireNonNull(remappingFunction);
    V oldValue;
    if ((oldValue = get(key)) != null) {
        V newValue = remappingFunction.apply(key, oldValue);
        if (newValue != null) {
            put(key, newValue);
            return newValue;
        } else {
            remove(key);
            return null;
        }
    } else {
        return null;
    }
}

2.8 replace

// replace(K key, V value)
// replace(K key, V oldValue, V newValue) (替换)
@Test
public void replace() {
    hashMap.put(1, zhangsan);
    hashMap.put(2, lisi);
    hashMap.replace(1, zhangtieniu);
    hashMap.replace(2, null);
    hashMap.replace(3, zhangtieniu);
    hashMap.replace(2, null, zhangtieniu);
    log.info("map: {}", hashMap);
    //map: {1=User(id=3, name=张铁牛), 2=User(id=3, name=张铁牛)}
}
  1. 替换指定key的value值
  2. 可以将对应的value设置为null
  3. 对应的key不存在时不会添加新元素
  4. replace(K key, V oldValue, V newValue)方法多了一层判断, 当key对应的value与oldValue相等时, 才会替换newValue

可以理解为 替换指定key的value值

源码如下:

default V replace(K key, V value) {
    V curValue;
    if (((curValue = get(key)) != null) || containsKey(key)) {
        curValue = put(key, value);
    }
    return curValue;
}

default boolean replace(K key, V oldValue, V newValue) {
    Object curValue = get(key);
    if (!Objects.equals(curValue, oldValue) ||
        (curValue == null && !containsKey(key))) {
        return false;
    }
    put(key, newValue);
    return true;
}

2.9 merge

// merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) (融合)
@Test
public void merge() {
    hashMap.put(1, zhangsan);
    User user1 = hashMap.merge(1, lisi, (oldValue, defaultValue) -> zhangtieniu);
    User user2 = hashMap.merge(2, lisi, (oldValue, defaultValue) -> zhangtieniu);
    log.info("map: {}, user1: {}, user2: {}", hashMap, user1, user2);
    //map: {1=User(id=3, name=张铁牛), 2=User(id=2, name=李四)}, user1: User(id=3, name=张铁牛), user2: User(id=2, name=李四)
}
  1. oldValue == null : 使用传进来的 value 作为newValue, oldValue != null : 使用remappingFunction的返回值作为newValue

    • newValue == null : 移除元素 & 返回newValue

    • newValue != null : 覆盖元素 & 返回newValue

可以理解为 融合三个值 分别为:

  1. key对应的value(oldValue)
  2. merge方法的第二个参数value (可以理解为oldValue的defaultValue)
  3. merge方法的第三个参数remappingFunction方法的返回值

融合逻辑为: 如果key对应的value不存在时, 使用merge方法的第二个参数value作为newValue, 如果key对应的value存在时,使用remappingFunction的返回值作为newValue, 如果newValue不为null则覆盖元素, 为null则移除元素

源码如下:

    default V merge(K key, V value,
            BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        Objects.requireNonNull(value);
        V oldValue = get(key);
        V newValue = (oldValue == null) ? value :
                   remappingFunction.apply(oldValue, value);
        if(newValue == null) {
            remove(key);
        } else {
            put(key, newValue);
        }
        return newValue;
    }
}

2.10 foreach

// foreach java8 新增
@Test
public void foreach() {
    hashMap.put(1, zhangsan);
    hashMap.put(2, lisi);
    hashMap.forEach((key, value) -> log.info("key: {}, value: {}", key, value));
    //key: 1, value: User(id=1, name=张三)
    //key: 2, value: User(id=2, name=李四)
}

3. 总结

方法名称 方法参数 方法描述 方法特点
put key, value 添加元素 hashmap/linkedhashmap: key, value 都可以为null
getOrDefault key, defaultValue 获取元素 当map中没有对应的key时, 返回defaultValue
putIfAbsent key, value 当不存在时添加元素 这里不存在指的是: key对应的旧值为null
compute key, BiFunction<key, oldValue, newValue> remappingFunction 重新计算key对应的value 使用remappingFunction的返回值替换key的旧值
computeIfAbsent key, Function<key, value> mappingFunction 当不存在时计算 这里不存在指的是: key对应的旧值为null, 与putIfAbsent方法逻辑类似
computeIfPresent key, BiFunction<key, oldValue, newValue> remappingFunction 当存在时计算 这里存在指的是: key对应的旧值!=null
replace key, value 替换元素 替换指定key的value, 不会添加元素
merge key, value, BiFunction<oldValue, value, newValue> remappingFunction 融合 融合key的旧值, 默认值, remappingFunction的返回值作为新值
foreach BiConsumer<key, value> 遍历 java8新加的遍历方式

标签:Map,hashMap,oldValue,value,忽略,User,key,null,好用
From: https://www.cnblogs.com/ludangxin/p/18655751

相关文章

  • js数组实例方法-lastIndexOf,join,keys,map
    Array.prototype.lastIndexOf()lastIndexOf()方法返回数组中给定元素最后一次出现的索引,如果不存在则返回-1。该方法从fromIndex开始向前搜索数组语法lastIndexOf(searchElement)lastIndexOf(searchElement,fromIndex)参数searchElement:被查找的元素fromIndex:以......
  • 分享几个好用的电商API接口(可测试)
    以下是一些好用的电商API接口,涵盖了商品、订单、支付、用户等多个方面:获取APIkey测试一、商品相关API接口商品详情接口功能:根据商品ID查询商品的详细信息,包括SKU信息、详情主图、库存、销量等。示例接口名:item_get。应用平台:1688、淘宝等。商品搜索接口功能:根据用户输......
  • 2025年简单好用的电脑桌面便签记事本软件
    在新的一年,很多打工人希望自己可以更加高效工作,把每件事管理的井井有条,实现升职加薪。每天使用电脑办公,想要随手记录工作事项、零散琐事,用一款电脑桌面便签或记事本软件是非常方便的。今天为大家推荐一款2025年简单又好用的电脑桌面便签记事本软件:敬业签!~桌面悬挂超方便它的......
  • 内衣洗衣机哪个牌子好用?高品质的洗内裤专用洗衣机推荐
    在大部分的家庭里都会有一台传统的洗衣机,但人们对于内衣物的清洗往往选择手洗,无非就是为了卫生。但是对于内衣物上的污渍,光靠我们的手洗是很难洗干净的。而且尽管能够把大部分的污渍清洗掉,但是所用来手洗的水和肥皂都不能完全除去内衣物上的各种细菌,还会在内衣物上滋生细菌。长......
  • 内衣裤洗衣机哪个牌子好?2025年度好用的内裤洗衣机
    在机器解放了双手的时代中,洗衣机走进了千家万户,虽然在某种程度上缓解了人们手洗衣服的压力,但还是有不少人选择了人工手洗自己的内衣内裤,甚至连袜子都是手工洗的,这让人很是郁闷,倒不是说洗衣机不方便,而是衣服混合在一起,很容易造成交叉感染,想想都觉得可怕。而内衣洗衣机的出现,恰好......
  • 在 mapper 中如何传递多个参数
    在MyBatis中,如果你需要在Mapper中传递多个参数,有几种方法可以实现。以下是几种常见的方法:方法1:使用 @Param 注解在Mapper接口中使用@Param注解来指定参数名称。这样可以在SQL语句中通过名称引用这些参数。示例假设你有一个表users,需要根据用户名和电子邮件查询用户。1.......
  • Mysql8忽略大小写的解决方案.240105
    ​一、删除服务器数据文件由于8.0没法设置参数后重启(失败),所以必须删掉老库,重新启动才行。切记:;本步骤要删掉老库所有资料,如果是数据库当前有用,请做好备份,再进行操作。systemctlstopmysqldcd/var/lib/mysql默认数据在这里rm-rf*二、添加配置,大小写不敏感vim/etc/m......
  • 安装zmap
    yuminstallcmakegmp-develgengetoptlibpcap-develflexbyaccjson-c-devellibunistring-develgcc-c++cmake报错提示没有Judy,需要安装直接yuminstallJudy*makemakeinstallzmap--versionzmap-p80,443,1080-oraw_ips.txt看下记录跑了几分钟参考:Fus......
  • 《Java核心技术II》用flatMap构建Optional值的函数
    用flatMap构建Optional值的函数假设你有一个可以产生Optional对象的方法f,并且目标T具有一个产生Optional对象的方法g。都是普通方法,可以通过调用s.f().g()将它们组合起来。这种组合无法工作,s.f()是Optional而不是T.需要调用:Optionalresult=s.f().flatMap(T::g);s.f()存......
  • 【划重点】90%的人都会忽略!跨网文件安全交换需要注意的问题
    跨网文件安全交换是现代企业日常运营中的一个关键环节,尤其是在内外网(例如公司内部网络与外部供应商、客户之间的文件传输),或者内部不同隔离网之间进行数据交换时。由于涉及敏感信息的交换,任何疏忽都可能带来数据泄露、恶意攻击等安全隐患。企业在进行跨网文件传输时,常常会忽视一些......