compute函数compute函数,其实和computeIfPresent、computeIfAbcent函数是类似的,不过它不关心map中到底有没有值,都执行lambda表达式计算新值并放入map中并返回 。
这个函数适合做分组迭代计算,像分组汇总金额的情况,就适合使用compute函数,如下:
List<Payment> payments = getPayments();Map<Integer, BigDecimal> amountByTypeMap = new HashMap<>();for(Payment payment : payments){amountByTypeMap.compute(payment.getPayTypeId(),(key, oldVal) -> oldVal == null ? payment.getAmount() : oldVal.add(payment.getAmount()));}
当oldValue是null,表示map中第一次计算相应key的值,直接给amount就好,而后面再次累积计算时,直接通过add函数汇总就好 。
merge函数可以发现,上面在使用compute汇总金额时,lambda表达式中需要判断是否是第一次计算key值,稍微麻烦了点,而使用merge函数的话,可以进一步简化代码,如下:
List<Payment> payments = getPayments();Map<Integer, BigDecimal> amountByTypeMap = new HashMap<>();for(Payment payment : payments){amountByTypeMap.merge(payment.getPayTypeId(), payment.getAmount(), BigDecimal::add);}
这个函数太简洁了,merge的第一个参数是key,第二个参数是value,第三个参数是值合并函数 。当是第一次计算相应key的值时,直接放入value到map中,后面再次计算时,使用值合并函数BigDecimal::add
计算出新的汇总值,并放入map中即可 。
putIfAbsent函数putIfAbsent从命名上也能知道作用了,当map中没有相应key时才put值到map中,主要用于如下场景:如将list转换为map时,若list中有重复值时,put与putIfAbsent的区别如下:
- put保留最晚插入的数据 。
- putIfAbsent保留最早插入的数据 。
for(Map.Entry<String, BigDecimal> entry: amountByTypeMap.entrySet()){Integer payTypeId = entry.getKey();BigDecimal amount = entry.getValue();System.out.printf("payTypeId: %s, amount: %s \n", payTypeId, amount);}
再看看在python或go中的写法,如下:for payTypeId, amount in amountByTypeMap.items():print("payTypeId: %s, amount: %s \n" % (payTypeId, amount))
可以发现,在python中的map遍历写法要少写好几行代码呢,不过,虽然java在语法层面上并未支持这种写法,但使用map的forEach函数,也可以简化出类似的效果来,如下:amountByTypeMap.forEach((payTypeId, amount) -> {System.out.printf("payTypeId: %s, amount: %s \n", payTypeId, amount);});
总结一直以来,java因代码编写太繁琐而被开发者们所广泛诟病,但从java8开始,从Map、Stream、var、multiline-string再到record,java在代码编写层面做了大量的简化,java似乎开窍了【Java8中那些方便又实用的Map函数】
经验总结扩展阅读
- 【JAVA】详解在JAVA中int与Integer的区别以及背后的原因。
- 哪些星座恋爱后特别会说话
- 蛇生肖与什么生肖最配
- 生肖鸡配什么生肖为好人
- 什么生肖鼠配什么生肖好
- 崩坏3永恒的礼堂怎么获取
- 暗黑破坏神:不朽茧中的求救声奇遇事件怎么完成
- 第五人格鹤翁位置在哪
- 射雕英雄传中穆易的真名是什么?
- 小七方冷是什么电视剧中的人物?