戳蓝字「TopCoder」关注咱们哦!java
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时就会报异常了,因此,在开发中若是不能保证lambda
的Collectors.toMap
元素不重复,那么就须要自定义mergeFunction
,能够将示例代码更改以下就能够了。app
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)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。