博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java8 Collectors.toMap的坑
阅读量:6543 次
发布时间:2019-06-24

本文共 2169 字,大约阅读时间需要 7 分钟。

按照常规思维,往一个map里put一个已经存在的key,会把原有的key对应的value值覆盖,然而通过一次线上问题,发现Java8中的Collectors.toMap反其道而行之,它默认给抛异常,抛异常...

 

线上业务代码出现Duplicate Key的异常,影响了业务逻辑,查看抛出异常部分的代码,类似以下写法:

1 Map
map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName));

 

然后list里面有id相同的对象,结果转map的时候居然直接抛异常了。。查源码发现toMap方法默认使用了个throwingMerger

1 public static 
2 Collector
> toMap(Function
keyMapper, 3 Function
valueMapper) { 4 return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new); 5 } 6 7 8 private static
BinaryOperator
throwingMerger() { 9 return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };10 }

 

那么这个throwingMerger是哪里用的呢?

1 public static 
> 2 Collector
toMap(Function
keyMapper, 3 Function
valueMapper, 4 BinaryOperator
mergeFunction, 5 Supplier
mapSupplier) { 6 BiConsumer
accumulator 7 = (map, element) -> map.merge(keyMapper.apply(element), 8 valueMapper.apply(element), mergeFunction); 9 return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);10 }

 

这里传进去的是HashMap,所以最终走的是HashMap的merge方法。merge方法里面有这么一段代码:

1 if (old != null) { 2     V v; 3     if (old.value != null) 4         v = remappingFunction.apply(old.value, value); 5     else 6         v = value; 7     if (v != null) { 8         old.value = v; 9         afterNodeAccess(old);10     }11     else12         removeNode(hash, key, null, false, true);13     return v;14 }

 

相信只看变量名就能知道这段代码啥意思了。。如果要put的key已存在,那么就调用传进来的方法。而throwingMerger的做法就是抛了个异常。所以到这里就可以知道写的代码为什么呲了。。

 

如果不想抛异常的话,自己传进去一个方法即可,上述代码可以改成:

1 Map
map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(oldValue, newValue) -> newValue));

 

这样就做到了使用新的value替换原有value。

 

写代码调方法时,多看源码实现,注意踩坑!

转载于:https://www.cnblogs.com/z941030/p/9648363.html

你可能感兴趣的文章
中国最强的人工智能学术会议来了
查看>>
Metasploit的射频收发器功能 | Metasploit’s RF Transceiver Capabilities
查看>>
主库 归档 删除策略
查看>>
《Linux从入门到精通(第2版)》——导读
查看>>
路过下载攻击利用旧版 Android 漏洞安装勒索软件
查看>>
ThinkSNS 六大子版本体验及源码下载
查看>>
《算法基础》——1.5实际因素
查看>>
《Java数字图像处理:编程技巧与应用实践》——第3章 基本Swing UI组件与图像显示 3.1 JPanel组件与BufferedImage对象的显示...
查看>>
为什么有人讨厌 Google 的新 Logo?
查看>>
腾讯2017暑期实习编程题3
查看>>
Intellij IDEA 构建Spring Web项目 — 用户登录功能
查看>>
[AHOI2013]作业
查看>>
git push被忽略的文件 处理
查看>>
C#中用ILMerge将所有引用的DLL打成一个DLL文件
查看>>
PHP生成HTML静态页面
查看>>
Makefile 中:= ?= += =的区别【转】
查看>>
使用makecontext实现用户线程【转】
查看>>
Comet:基于 HTTP 长连接的“服务器推”技术
查看>>
BZOJ 2733: [HNOI2012]永无乡 启发式合并treap
查看>>
四种方法校验数组中是否包含某个指定的字符串
查看>>