前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java lambda 容易掉进的2个坑

java lambda 容易掉进的2个坑

作者头像
luoxn28
发布2019-11-06 17:39:19
1.3K0
发布2019-11-06 17:39:19
举报
文章被收录于专栏:TopCoderTopCoder
JDK8通过引入Lambda,小伙伴们不用再写大量的匿名内部类。事实上,还有更多由于函数式编程本身特性带来的提升。比如:代码的可读性会更好、高阶函数引入了函数组合的概念。此外,因为Lambda的引入,集合操作也得到了极大的改善。比如,引入stream API,把map、reduce、filter这样的基本函数式编程的概念与Java集合结合起来。在大多数情况下,处理集合时,Java程序员可以告别for、while、if这些语句。随之而来的是,map、reduce、filter等操作都可以并行化,在一些条件下,可以提升性能。

但是如果lambda的使用姿势不对,会造成意向不到的问题。下面就总结几个常见的Java lambda坑(不正确的使用姿势)~

Collectors.toMap报Duplicate key异常

首先看下以下代码:

代码语言:javascript
复制
// 将list转换成map接口
List<String> list = Arrays.asList("a", "b", "c", "a");
        Map<String, String> map = list.stream().collect(Collectors.toMap(k -> k, v -> v));
        System.out.println(map);

直接执行代码会报异常:

代码语言:javascript
复制
Exception in thread "main" 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.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
    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)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)

这是为什么呢?因为默认情况下,也就是Collectors.toMap(k -> k, v -> v)未指定BinaryOperator<U> mergeFunction时,使用的mergeFunction为:

代码语言:javascript
复制
(u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };

这样在出现重复key时就会报异常了,所以,在开发中如果不能保证lambdaCollectors.toMap元素不重复,那么就需要自定义mergeFunction,可以将示例代码更改如下就可以了。

代码语言:javascript
复制
List<String> list = Arrays.asList("a", "b", "c", "a");
        // v1表示old value,v2表示current value
        Map<String, String> map = list.stream().collect(Collectors.toMap(k -> k, v -> v, (v1, v2) -> v1));
        System.out.println(map);

findFirst空指针异常

首先看下如下代码:

代码语言:javascript
复制
List<String> list = Arrays.asList("a", "b", "c");
        String value = list.stream().map(o -> o.equals("a") ? null : o)
                .findFirst().orElse(null);
        System.out.println(value);

以上代码执行会报空指针,异常信息如下:

代码语言:javascript
复制
Exception in thread "main" java.lang.NullPointerException
    at java.util.Objects.requireNonNull(Objects.java:203)
    at java.util.Optional.<init>(Optional.java:96)
    at java.util.Optional.of(Optional.java:108)
    at java.util.stream.FindOps$FindSink$OfRef.get(FindOps.java:193)
    at java.util.stream.FindOps$FindSink$OfRef.get(FindOps.java:190)
    at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464)

因为findFirst使用的是Optional.of,而Optional.of要求元素必须非null,所以会报空指针,上述代码很容易看出来,如果findFirst前置逻辑较复杂,可能会疏忽元素可能为null情况,因为最好在执行findFirst前加上一个filter(Objects::nonNull)的逻辑。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 TopCoder 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Collectors.toMap报Duplicate key异常
  • findFirst空指针异常
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档