详解Java Streams 中的异常处理
前言:
stream api 和 lambda 是java8的重要特性让我们可以使用更具功能性的语法风格。但是在编写的代码时候一个更大的问题是如何处理lambda中的已检查异常。
但是不能直接调用从lambda抛出异常!但是可以在lambda中做一个简单的try-catch并将异常包装成一个runtimeexception。
/**###很显然这不是一种好的表现方式##**/ /** * 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); }
换一种可读性比较好的方式呢?
/**将函数体提取到一个单独的方法中,并调用新方法做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内部调用。如果每个调用都进行运行时异常的捕获,重复代码就出现了。所以:将它抽象为实用函数,每次需要的时候调用它!
//定义一个检查接口 @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); } }; }
/**调用公共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
使用流时如果发生异常不希望停止处理流,either类型是函数式语言中的常见类型而不是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 +")"; } }
让函数返回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)); } }; }
/**调用either.lift 捕获异常继续执行*/ 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); }
总结:
如果你想在lambda中调用它checkedexception,你可以将其包装成一个runtimeexception 。建议您创建一个抽象进行调用,这样您就不会每次try/catch。也可以使用 either 或其他类型来包装函数的结果,使流不会终止。
以上所述是小编给大家介绍的java streams 中的异常处理详解整合,希望对大家有所帮助
上一篇: spring的父子容器及配置详解
下一篇: 研究了一下div+css的高度自适应问题