专栏首页TopCoderjava lambda 容易掉进的2个坑

java lambda 容易掉进的2个坑

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

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

Collectors.toMap报Duplicate key异常

首先看下以下代码:

// 将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);

直接执行代码会报异常:

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为:

(u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };

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

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空指针异常

首先看下如下代码:

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);

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

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)的逻辑。

本文分享自微信公众号 - TopCoder(gh_12e4a74a5c9c),作者:南

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 彻底搞懂 netty 线程模型

    netty线程模型netty单线程模型Reactor多线程模型Reactor主从多线程模型netty线程模型思考netty线程模型实践

    luoxn28
  • 分布式锁设计与实现

    •排他性:任意时刻,只能有一个client能获取到锁•容错性:分布式锁服务一般要满足AP,也就是说,只要分布式锁服务集群节点大部分存活,client就可以进行加...

    luoxn28
  • Eureka 原理分析

    注册中心是分布式开发的核心组件之一,而eureka是spring cloud推荐的注册中心实现,因此对于Java开发同学来说,还是有必要学习eureka的,特别...

    luoxn28
  • JDK8 stream toMap() java.lang.IllegalStateException: Duplicate key异常解决(key重复)

    测试又报bug啦 接到测试小伙伴的问题,说是一个接口不返回数据了,好吧,虽然不是我写的接口任务落到头上也得解决,本地调试了一下,好家伙,直接抛了个异常出来,这又...

    我是十三
  • 我的开发日记(四)

    今天有点跟mysql和mybatis杠上了,解决了两个问题都是这方面的,特别是复杂SQL在XML配置文件中的设置有点怀疑人生的感觉。

    FunTester
  • The consumer group[PushConsumer] has been created before, specify another name please

    MickyInvQ
  • 2019-03-17 生产系统cup100%负载问题解决

    Arthas支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

    Albert陈凯
  • spring boot 启动 NoClassDefFoundError: org/springframework/core/ErrorCoded 报错

    MickyInvQ
  • spring boot 启动报错Log4j2 could not find a logging implementation 解决

    MickyInvQ
  • java.lang.ClassNotFoundException: org.apache.commons.fileupload.FileItemFactory

    1、启动项目报出这个错误,未找到响应的包,所以需要你将包从远程仓库下载到本地仓库即可。

    别先生

扫码关注云+社区

领取腾讯云代金券