Java8:Java8 中 Map 接口的新方法

查看compute 方法的API 文档,可以发现compute方法与如下代码等价

V oldValue = map.get(key);

V newValue = remappingFunction.apply(key, oldValue);

if (oldValue != null ) {

if (newValue != null)

map.put(key, newValue);

else

map.remove(key);

} else { // 即 原来的 key 不存在 Map 中或该 key 关联的 value 为 null

if (newValue != null)

map.put(key, newValue);

else

return null;

}

compute方法和原来put方法的区别在于:

put(K key, V value) 方法,如果 keyMap 中不存在,那么直接加入;如果已经存在,那么使用新的 value 替换旧的value

compute(K key, BiFunction remappingFunction)方法可以通过一个 BiFunction 来计算出新的valueBiFunction的参数为旧的 keyvalue,返回计算出新的value —— 与 put方法不同,compute方法返回的会是最新的与key 相关联的 value,而不是旧的 value

所以可以使用compute 方法改写 getElementPositions 如下:

public static Map<String, List> getElementPositions(List list) {

Map<String, List> positionsMap = new HashMap<>();

for (int i = 0; i < list.size(); i++) {

positionsMap.compute(list.get(i), (k, v) -> v == null ? new ArrayList<>(1) : v).add(i);

}

return positionsMap;

}

public static void main(String[] args) throws Exception {

List list = Arrays.asList(“a”, “b”, “b”, “c”, “c”, “c”, “d”, “d”, “d”, “f”, “f”, “g”);

System.out.println(“使用 compute:”);

Map<String, List> elementPositions = getElementPositions(list);

System.out.println(elementPositions);

}

(k, v) -> v == null ? new ArrayList<>(1) : v即 如果当前的 value 为 null,那么 该 BiFunction的返回值为 new ArrayList<>(1);如果不为 null,那么返回值便是本身。而且因为compute 方法会返回新的value —— 此时便是与 list.get(i)(key) 相关联的ArrayList —— 所以我们可以直接调用其add 方法。

运行结果:

使用 compute 的运行结果

很棒~ 还能更简洁吗? 我们再看看 computeIfAbsent 方法:

computeIfAbsentcompute 的关系,就类似于 putIfAbsentput的关系:

computeIfAbsentkey不在Map 中或者与key 相关联的valuenull时,才执行通过函数计算新 value 的操作,否则不执行;computeIfAbsent的返回值也是与 key 相关联的最新的 value。其默认实现如下:

computeIfAbsent 的默认实现

compute 不同,computeIfAbsent接受的函数操作是 Function 而不是 BiFunction—— 这很好理解,computeIfAbsent 只在key 不在 Map 中或者与 key相关联的 valuenull 时才执行函数操作,那么显然此时与 key相关的 valuenull,所以computeIfAbsent只接受 Function作为参数即可 —— 该 Function可以使用key作为参数计算出新的value。使用 computeIfAbsent 改写 getElementPositions

public static Map<String, List> getElementPositions(List list) {

Map<String, List> positionsMap = new HashMap<>();

for (int i = 0; i < list.size(); i++) {

positionsMap.computeIfAbsent(list.get(i), k -> new ArrayList<>(1)).add(i);

}

return positionsMap;

}

public static void main(String[] args) throws Exception {

List list = Arrays.asList(“a”, “b”, “b”, “c”, “c”, “c”, “d”, “d”, “d”, “f”, “f”, “g”);

System.out.println(“使用 computeIfAbsent:”);

Map<String, List> elementPositions = getElementPositions(list);

System.out.println(elementPositions);

}

运行结果:

使用 computeIfAbsent 的运行结果

事实上,本文使用 putIfAbsent 时是存在问题的,positionsMap.putIfAbsent(str, new ArrayList<>(1)); 这句代码每次调用时都会产生一个临时的 ArrayList—— 当遍历的List<String>较大时,这可能会带来一定的负面影响;相比之下 computecomputeIfAbsent 的好处在于,它们接受的参数为函数,只会在必要时才使用函数进行计算得出新value。在本文类似需求的情况下,就适用性和简洁性而言,computeIfAbsent要优于compute。在 JDK1.8 的 API 文档中,也说到在需要生成一个类似于 Map<K, Collection<V>> 的结构时,computeIfAbsent 很适合这种情况:

computeIfAbsent 的 JavaDoc 文档

compute方法适用于什么情况呢?从前面的介绍可知,compute 方法更适用于更新 key关联的 value时,新值依赖于旧值的情况 —— 比如统计一个 List<String> 中每个元素出现的次数:

public static Map<String, Integer> getElementCounts(List list) {

Map<String, Integer> countsMap = new HashMap<>();

list.forEach(str -> countsMap.compute(str, (k, v) -> v == null ? 1 : v + 1)); // 此时:新值 = 旧值 + 1

return countsMap;

}

public static void main(String[] args) throws Exception {

List list = Arrays.asList(“a”, “b”, “b”, “c”, “c”, “c”, “d”, “d”, “d”, “f”, “f”, “g”);

System.out.println(“使用 compute 计算元素出现的次数:”);

Map<String, Integer> counts = getElementCounts(list);

System.out.println(counts);

}

运行结果:

使用 compute 计算元素出现的次数

Java8中还为Map添加了一些其他方便于编码的新方法,请有兴趣的读者继续发掘。

原文地址:https://segmentfault.com/a/1190000007838166

推荐


大厂笔试内容集合(内有详细解析) 持续更新中…

ProcessOn是一个在线作图工具的聚合平台~

文末


欢迎关注个人微信公众号:Coder编程

欢迎关注Coder编程公众号,主要分享数据结构与算法、Java相关知识体系、框架知识及原理、Spring全家桶、微服务项目实战、DevOps实践之路、每日一篇互联网大厂面试或笔试题以及PMP项目管理知识等。更多精彩内容正在路上~

新建了一个qq群:315211365,欢迎大家进群交流一起学习。谢谢了!也可以介绍给身边有需要的朋友。

文章收录至
Github: https://github.com/CoderMerlin/coder-programming

最后

即使是面试跳槽,那也是一个学习的过程。只有全面的复习,才能让我们更好的充实自己,武装自己,为自己的面试之路不再坎坷!今天就给大家分享一个Github上全面的Java面试题大全,就是这份面试大全助我拿下大厂Offer,月薪提至30K!

我也是第一时间分享出来给大家,希望可以帮助大家都能去往自己心仪的大厂!为金三银四做准备!
一共有20个知识点专题,分别是:

Dubbo面试专题

JVM面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Java并发面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Kafka面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

MongDB面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

MyBatis面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

MySQL面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Netty面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

RabbitMQ面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Redis面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Spring Cloud面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

SpringBoot面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

zookeeper面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

常见面试算法题汇总专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

计算机网络基础专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

设计模式专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

714323392468)]

SpringBoot面试专题

[外链图片转存中…(img-dyF5Bdub-1714323392468)]

zookeeper面试专题

[外链图片转存中…(img-fqMylyUC-1714323392469)]

常见面试算法题汇总专题

[外链图片转存中…(img-bS2r2ExP-1714323392469)]

计算机网络基础专题

[外链图片转存中…(img-PZf6Y4uL-1714323392469)]

设计模式专题

[外链图片转存中…(img-miFwD75K-1714323392470)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值