JAVA8-lambda表达式5:toMap引发的线上故障

  • Post author:
  • Post category:java



目录


先看一串代码


不平凡的2020


mergeFunction


指定冲突处理函数


小心toMap有坑


先看一串代码

dbTaxiDrivers.ifPresent((drivers) -> {
            map.putAll(drivers.stream()
                .collect(Collectors.toMap(TaxiDriverInfo::getOperationId, item -> item)));
        });

里面用到了java8的高级收集器:toMap

相信很多人都用过这个方法,那这段代码到底有没有问题?我最开始以为没有,不就是转换成map吗,能有什么问题,至到吃过亏了,才知道其它有个坑在这,稍不注意就掉坑了。

这不,前阵子有个同事又踩坑了,还是大坑

不平凡的2020

今年的春节来的格外早。

然后又是百年不遇的新冠疫情,但是(注意这个但是!一般这个词出现的时候,就是要搞事情了),班还是要上的。

为了抗击疫情,我司也开发了一个疫情模块,在APP上为海外同胞提供二手数据(估计也是爬来的)。

所以就有了类似上面的一串代码,其中toMap出场了:Collectors.toMap

上线后,第一天,相安无事,皆大欢喜,都准备写PPT吹水了。。。

第二天,线上狂报警:XX模块迭0,一看日志,出现了类似如下错误:

java.lang.IllegalStateException: Duplicate key a

	at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
	at java.util.HashMap.merge(HashMap.java:1254)
	at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
	at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)

主键冲突!!!


如果Map的key里面有重复值,Collectors.toMap会报主键重复的错误

mergeFunction

源码中看下报错的异常

根据堆栈,得到报错的地方,HashMap里面的mergeFunction

从上面的代码里面可以看出,如果有值重复,则会执行mergeFunction,默认为抛出异常

那么如果出现主键重复的情况,该如何处理呢?

指定冲突处理函数

默认的处理函数是抛出函数

再来看看另外一个函数toMap,就是可以手动传入mergeFunction

重写一下上面那个例子

List<String> list = Lists.newArrayList();
        list.add("a");
        list.add("a");

        Map<String, String> map = list.stream().collect(Collectors.toMap(a -> a, Function.identity(), (oldValue, newValue) -> newValue));

运行上面的例子,将会正常运行,在上面指定了mergeFunction:(oldValue, newValue) -> newValue,表示以新值覆盖旧值!

这样,开发者又可以主动处理这种情况了

小心toMap有坑

总之一句话,用toMap要小心,主键重复处理的情况,如果有重复,需要指定mergeFunction,否则就半夜应急吧



版权声明:本文为weigeshikebi原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。