詳解Java Streams 中的異常處理
前言:
Stream API 和 Lambda 是Java8的重要特性讓我們可以使用更具功能性的語法風格。但是在編寫的代碼時候一個更大的問題是如何處理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ù)體提取到一個單獨的方法中,并調(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
在許多情況下對于一些運行時異常的捕捉都使用 RuntimeException 也可以在lambda內(nèi)部調(diào)用。如果每個調(diào)用都進行運行時異常的捕獲,重復代碼就出現(xiàn)了。所以:將它抽象為實用函數(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 進行異常處理*/ 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)用它checkedException,你可以將其包裝成一個RuntimeException 。建議您創(chuàng)建一個抽象進行調(diào)用,這樣您就不會每次try/catch。也可以使用 Either 或其他類型來包裝函數(shù)的結(jié)果,使流不會終止。
以上所述是小編給大家介紹的Java Streams 中的異常處理詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
springboot動態(tài)調(diào)用實現(xiàn)類方式
這篇文章主要介紹了springboot動態(tài)調(diào)用實現(xiàn)類方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11SpringBoot項目如何設(shè)置權(quán)限攔截器和過濾器
這篇文章主要介紹了使用lombok時如何自定義get、set方法問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07SpringBoot增強Controller方法@ControllerAdvice注解的使用詳解
這篇文章主要介紹了SpringBoot增強Controller方法@ControllerAdvice注解的使用詳解,@ControllerAdvice,是Spring3.2提供的新注解,它是一個Controller增強器,可對controller進行增強處理,需要的朋友可以參考下2023-10-10關(guān)于ApplicationContext的三個常用實現(xiàn)類
這篇文章主要介紹了關(guān)于ApplicationContext的三個常用實現(xiàn)類,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06