戳藍字「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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。