详解Java Streams 中的异常处理
前言:
StreamAPI和Lambda是Java8的重要特性让我们可以使用更具功能性的语法风格。但是在编写的代码时候一个更大的问题是如何处理lambda中的已检查异常。
但是不能直接调用从Lambda抛出异常!但是可以在Lambda中做一个简单的try-catch并将异常包装成一个RuntimeException。
/**###很显然这不是一种好的表现方式##**/ /** *dosomething *@paramitem *@return */ privatestaticObjectdoSomething(Stringitem){ System.out.println("doSomething:\t"+item); returnitem; } publicstaticvoidmain(String[]args){ ListmyList=Arrays.asList("1","2","3","4","5","6"); myList.stream().map(item->{ try{ returndoSomething(item); }catch(Exceptione){ thrownewRuntimeException(e); } }).forEach(System.out::println); }
换一种可读性比较好的方式呢?
/**将函数体提取到一个单独的方法中,并调用新方法做try-catch处理**/ privateObjectdoSomething(Stringitem){ System.out.println("doSomething:\t"+item); returnitem; } privateObjecttrySomething(Stringitem){ try{ returndoSomething(item); }catch(Exceptione){ thrownewRuntimeException(e); } } publicvoidmap(){ ListmyList=Arrays.asList("1","2","3","4","5","6"); myList.stream().map(this::doSomething).forEach(System.out::println); }
RuntimeException
在许多情况下对于一些运行时异常的捕捉都使用RuntimeException也可以在lambda内部调用。如果每个调用都进行运行时异常的捕获,重复代码就出现了。所以:将它抽象为实用函数,每次需要的时候调用它!
//定义一个检查接口 @FunctionalInterface publicinterfaceCheckedFunction{ Rapply(Tt)throwsException; }
您可以在此抽象接口中处理try-catch并将原始异常包装到RuntimeException 中。
publicstaticFunction wrap(CheckedFunction checkedFunction){ returnt->{ try{ returncheckedFunction.apply(t); }catch(Exceptione){ thrownewRuntimeException(e); } }; }
/**调用公共wrap进行异常处理*/ publicvoidmap(){ ListmyList=Arrays.asList("1","2","3","4","5","6"); myList.stream() .map(wrap(item->doSomething(item))) .forEach(System.out::println); }
Either
使用流时如果发生异常不希望停止处理流,Either类型是函数式语言中的常见类型而不是Java的一部分。与Java中的Optional类型类似,Either是具有两种可能性的通用包装器。例如,如果我们有一个Either值,那么这个值可以包含String类型或Integer类型Either
publicclassEither{ privatefinalLleft; privatefinalRright; privateEither(Lleft,Rright){ this.left=left; this.right=right; } publicstatic Either Left(Lvalue){ returnnewEither(value,null); } publicstatic Either Right(Rvalue){ returnnewEither(null,value); } publicOptional getLeft(){ returnOptional.ofNullable(left); } publicOptional getRight(){ returnOptional.ofNullable(right); } publicbooleanisLeft(){ returnleft!=null; } publicbooleanisRight(){ returnright!=null; } public Optional mapLeft(Functionmapper){ if(isLeft()){ returnOptional.of(mapper.apply(left)); } returnOptional.empty(); } public Optional mapRight(Functionmapper){ if(isRight()){ returnOptional.of(mapper.apply(right)); } returnOptional.empty(); } publicStringtoString(){ if(isLeft()){ return"Left("+left+")"; } return"Right("+right+")"; } }
让函数返回Either而不是抛出一个Exception.
//只记录异常 publicstaticFunction lift(CheckedFunction function){ returnt->{ try{ returnEither.Right(function.apply(t)); }catch(Exceptionex){ returnEither.Left(ex); } }; } //记录异常和值 publicstatic Function liftWithValue(CheckedFunction function){ returnt->{ try{ returnEither.Right(function.apply(t)); }catch(Exceptionex){ returnEither.Left(Pair.of(ex,t)); } }; }
/**调用Either.lift捕获异常继续执行*/ publicvoidmap(){ ListmyList=Arrays.asList("1","2","3","4","5","6"); myList.stream() .map(Either.lift(item->doSomething(item))) .forEach(System.out::println); }
总结:
如果你想在Lambda中调用它checkedException,你可以将其包装成一个RuntimeException。建议您创建一个抽象进行调用,这样您就不会每次try/catch。也可以使用 Either或其他类型来包装函数的结果,使流不会终止。
以上所述是小编给大家介绍的JavaStreams中的异常处理详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!