Java8中Stream使用的一個注意事項
Stream簡介
我們先來看看Java里面是怎么定義Stream的:
A sequence of elements supporting sequential and parallel aggregate operations.
我們來解讀一下上面的那句話:
- Stream是元素的集合,這點讓Stream看起來用些類似Iterator;
- 可以支持順序和并行的對原Stream進行匯聚的操作;
大家可以把Stream當成一個高級版本的Iterator。原始版本的Iterator,用戶只能一個一個的遍歷元素并對其執(zhí)行某些操作;高級版本的Stream,用戶只要給出需要對其包含的元素執(zhí)行什么操作,比如“過濾掉長度大于10的字符串”、“獲取每個字符串的首字母”等,具體這些操作如何應(yīng)用到每個元素上,就給Stream就好了?。ㄟ@個秘籍,一般人我不告訴他:))大家看完這些可能對Stream還沒有一個直觀的認識,莫急,咱們來段代碼。
//Lists是Guava中的一個工具類 List<Integer> nums = Lists.newArrayList(1,null,3,4,null,6); nums.stream().filter(num -> num != null).count();
上面這段代碼是獲取一個List中,元素不為null的個數(shù)。這段代碼雖然很簡短,但是卻是一個很好的入門級別的例子來體現(xiàn)如何使用Stream,正所謂“麻雀雖小五臟俱全”。
引子
今天下午遇到一個NPE,如下圖所示

跟了下源碼,最后跟到ReferencePipeline#193行,應(yīng)該是調(diào)用apply的時候,入?yún)為null,從而觸發(fā)了空指針異常。
@Override
@SuppressWarnings("unchecked")
public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
Objects.requireNonNull(mapper);
return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
return new Sink.ChainedReference<P_OUT, R>(sink) {
@Override
public void accept(P_OUT u) {
downstream.accept(mapper.apply(u));
}
};
}
};
}
為了驗證我的想法,我寫了如下的測試例子:
public static void main(String[] args) {
List<Long> res = Arrays.asList(1L, 2L, null);
res.stream().map(UserReadServiceImpl::get).collect(Collectors.toList());
}
public static Long get(long userId) {
return userId;
}
最佳實踐
- 在Streams開始和結(jié)束之前,都需要避免處理null值,使用filter可以過濾掉;
- 不要濫用Streams,因為我發(fā)現(xiàn)Stream有時候會讓代碼變得更難以閱讀;
- 針對Collections的迭代處理,可以多用Stream處理;
- 要謹慎使用Parallel Streams,性能不一定比普通的loop要好;
- 最后,對外暴露API的入?yún)z查需要更全面;
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
參考資料
Java SE 8最佳實踐](https://www.jfokus.se/jfokus17/preso/Java-SE-8-best-practices.pdf)
流處理線:ReferencePipeline](http://download.java.net/lambda/b72/docs/api/java/util/stream/ReferencePipeline.html)
相關(guān)文章
SpringBoot整合MyBatis和MyBatis-Plus請求后不打印sql日志的問題解決
本文主要介紹了SpringBoot整合MyBatis和MyBatis-Plus請求后不打印sql日志的問題解決文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧2024-07-07
SpringCloud使用FFmpeg對視頻壓縮處理的代碼示例
在現(xiàn)代的視頻處理系統(tǒng)中,壓縮視頻以減小存儲空間、加快傳輸速度是一項非常重要的任務(wù),FFmpeg作為一個強大的開源工具,廣泛應(yīng)用于音視頻的處理,包括視頻的壓縮和格式轉(zhuǎn)換等,本文將通過Java代碼示例,向您展示如何使用FFmpeg進行視頻壓縮,并介紹相關(guān)參數(shù)的設(shè)置2024-11-11
SpringBoot使用阿里oss實現(xiàn)文件上傳的流程步驟
云服務(wù)指的就是通過互聯(lián)網(wǎng)對外提供的各種各樣的服務(wù),比如像:語音服務(wù)、短信服務(wù)、郵件服務(wù)、視頻直播服務(wù)、文字識別服務(wù)、對象存儲服務(wù)等等,本文通過代碼示例和圖文給大家介紹了SpringBoot使用阿里oss實現(xiàn)文件上傳的流程步驟,需要的朋友可以參考下2025-01-01

