一、引子
今天下午遇到一個NPE,如下圖所示
- image.png
之前沒仔細查過Stream的源碼,也沒有深究背后的原因,今天跟了下源碼,最后跟到ReferencePipeline#193行,應該是調(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開始和結束之前,都需要避免處理null值,使用filter可以過濾掉;
- 不要濫用Streams,因為我發(fā)現(xiàn)Stream有時候會讓代碼變得更難以閱讀;
- 針對Collections的迭代處理,可以多用Stream處理;
- 要謹慎使用Parallel Streams,性能不一定比普通的loop要好;
- 最后:對外暴露API的入?yún)z查需要更全面;
參考資料
本號專注于后端技術、JVM問題排查和優(yōu)化、Java面試題、個人成長和自我管理等主題,為讀者提供一線開發(fā)者的工作和成長經(jīng)驗,期待你能在這里有所收獲。

javaadu
