詳解Java Streams 中的異常處理
前言:
Stream API 和 Lambda 是Java8的重要特性讓我們可以使用更具功能性的語法風(fēng)格。但是在編寫的代碼時候一個更大的問題是如何處理lambda中的已檢查異常。
但是不能直接調(diào)用從Lambda拋出異常!但是可以在Lambda中做一個簡單的try-catch并將異常包裝成一個RuntimeException。
/**###很顯然這不是一種好的表現(xiàn)方式##**/
/**
* dosomething
* @param item
* @return
*/
private static Object doSomething(String item) {
System.out.println("doSomething:\t" + item);
return item;
}
public static void main(String[] args) {
List<String> myList = Arrays.asList("1", "2", "3", "4", "5", "6");
myList.stream().map(item -> {
try {
return doSomething(item);
} catch (Exception e) {
throw new RuntimeException(e);
}
}).forEach(System.out::println);
}
換一種可讀性比較好的方式呢?
/**將函數(shù)體提取到一個單獨(dú)的方法中,并調(diào)用新方法做try-catch處理**/
private Object doSomething(String item) {
System.out.println("doSomething:\t" + item);
return item;
}
private Object trySomething(String item) {
try {
return doSomething(item);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void map() {
List<String> myList = Arrays.asList("1", "2", "3", "4", "5", "6");
myList.stream().map(this::doSomething).forEach(System.out::println);
}
RuntimeException
在許多情況下對于一些運(yùn)行時異常的捕捉都使用 RuntimeException 也可以在lambda內(nèi)部調(diào)用。如果每個調(diào)用都進(jìn)行運(yùn)行時異常的捕獲,重復(fù)代碼就出現(xiàn)了。所以:將它抽象為實(shí)用函數(shù),每次需要的時候調(diào)用它!
//定義一個檢查接口
@FunctionalInterface
public interface CheckedFunction<T,R> {
R apply(T t) throws Exception;
}
您可以在此抽象接口中處理try-catch并將原始異常包裝到 RuntimeException 中。
public static <T,R> Function<T,R> wrap(CheckedFunction<T,R> checkedFunction) {
return t -> {
try {
return checkedFunction.apply(t);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
/**調(diào)用公共wrap 進(jìn)行異常處理*/
public void map(){
List<String> myList = Arrays.asList("1", "2", "3", "4", "5", "6");
myList.stream()
.map(wrap(item -> doSomething(item)))
.forEach(System.out::println);
}
Either
使用流時如果發(fā)生異常不希望停止處理流,Either類型是函數(shù)式語言中的常見類型而不是Java的一部分。與Java中的Optional類型類似,Either是具有兩種可能性的通用包裝器。例如,如果我們有一個Either值,那么這個值可以包含String類型或Integer類型Either<String,Integer>。
public class Either<L, R> {
private final L left;
private final R right;
private Either(L left, R right) {
this.left = left;
this.right = right;
}
public static <L,R> Either<L,R> Left( L value) {
return new Either(value, null);
}
public static <L,R> Either<L,R> Right( R value) {
return new Either(null, value);
}
public Optional<L> getLeft() {
return Optional.ofNullable(left);
}
public Optional<R> getRight() {
return Optional.ofNullable(right);
}
public boolean isLeft() {
return left != null;
}
public boolean isRight() {
return right != null;
}
public <T> Optional<T> mapLeft(Function<? super L, T> mapper) {
if (isLeft()) {
return Optional.of(mapper.apply(left));
}
return Optional.empty();
}
public <T> Optional<T> mapRight(Function<? super R, T> mapper) {
if (isRight()) {
return Optional.of(mapper.apply(right));
}
return Optional.empty();
}
public String toString() {
if (isLeft()) {
return "Left(" + left +")";
}
return "Right(" + right +")";
}
}
讓函數(shù)返回Either 而不是拋出一個Exception.
//只記錄異常
public static <T,R> Function<T, Either> lift(CheckedFunction<T,R> function) {
return t -> {
try {
return Either.Right(function.apply(t));
} catch (Exception ex) {
return Either.Left(ex);
}
};
}
//記錄異常和值
public static <T,R> Function<T, Either> liftWithValue(CheckedFunction<T,R> function) {
return t -> {
try {
return Either.Right(function.apply(t));
} catch (Exception ex) {
return Either.Left(Pair.of(ex,t));
}
};
}
/**調(diào)用Either.lift 捕獲異常繼續(xù)執(zhí)行*/
public void map(){
List<String> myList = Arrays.asList("1", "2", "3", "4", "5", "6");
myList.stream()
.map(Either.lift(item -> doSomething(item)))
.forEach(System.out::println);
}
總結(jié):
如果你想在Lambda中調(diào)用它c(diǎn)heckedException,你可以將其包裝成一個RuntimeException 。建議您創(chuàng)建一個抽象進(jìn)行調(diào)用,這樣您就不會每次try/catch。也可以使用 Either 或其他類型來包裝函數(shù)的結(jié)果,使流不會終止。
以上所述是小編給大家介紹的Java Streams 中的異常處理詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
詳細(xì)談?wù)凧ava中l(wèi)ong和double的原子性
原子性是指一個操作或多個操作要么全部執(zhí)行,且執(zhí)行的過程不會被任何因素打斷,要么就都不執(zhí)行,下面這篇文章主要給大家介紹了關(guān)于Java中l(wèi)ong和double原子性的相關(guān)資料,需要的朋友可以參考下2021-08-08
springboot動態(tài)調(diào)用實(shí)現(xiàn)類方式
這篇文章主要介紹了springboot動態(tài)調(diào)用實(shí)現(xiàn)類方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
SpringBoot項(xiàng)目如何設(shè)置權(quán)限攔截器和過濾器
這篇文章主要介紹了使用lombok時如何自定義get、set方法問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
SpringBoot增強(qiáng)Controller方法@ControllerAdvice注解的使用詳解
這篇文章主要介紹了SpringBoot增強(qiáng)Controller方法@ControllerAdvice注解的使用詳解,@ControllerAdvice,是Spring3.2提供的新注解,它是一個Controller增強(qiáng)器,可對controller進(jìn)行增強(qiáng)處理,需要的朋友可以參考下2023-10-10
關(guān)于ApplicationContext的三個常用實(shí)現(xiàn)類
這篇文章主要介紹了關(guān)于ApplicationContext的三個常用實(shí)現(xiàn)類,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06
SpringMVC 傳日期參數(shù)到后臺的實(shí)例講解
下面小編就為大家分享一篇SpringMVC 傳日期參數(shù)到后臺的實(shí)例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12

