Java 8:Lambda-Streams - 按引发异常的方法进行过滤
Java 8 的 lambda 表达式提供了强大的方法来操作和处理数据。但是,在处理可能引发异常的方法时,了解 lambda 表达式的局限性并探索有效的解决方案非常重要。
问题:
考虑以下代码片段:
<code class="java">class Bank { public Set<String> getActiveAccountNumbers() throws IOException { Stream<Account> s = accounts.values().stream(); s = s.filter(a -> a.isActive()); Stream<String> ss = s.map(a -> a.getNumber()); return ss.collect(Collectors.toSet()); } } interface Account { boolean isActive() throws IOException; String getNumber() throws IOException; }</code>
由于 isActive 和 getNumber 方法抛出检查异常,此代码无法编译。仅仅捕获周围的 try-catch 块中的异常是不够的,因为 lambda 表达式中未正确处理异常。
解决方案:
克服这个问题,我们需要在异常转义 lambda 表达式之前捕获它们。一种方法是使用未经检查的异常,如以下修改后的代码片段所示:
<code class="java">s = s.filter(a -> { try { return a.isActive(); } catch (IOException e) { throw new UncheckedIOException(e); } });</code>
这里,我们在 lambda 内捕获 IOException 并抛出未经检查的异常,确保它在 lambda 内得到正确处理
或者,我们可以使用一个包装器方法,将已检查的异常转换为未检查的异常:
<code class="java">return s.filter(a -> uncheckCall(a::isActive)) .map(Account::getNumber) .collect(toSet()); public static <T> T uncheckCall(Callable<T> callable) { try { return callable.call(); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } }</code>
这允许我们将 lambda 表达式包装在对 uncheckCall 的调用中,后者处理在内部检查异常,使 lambda 表达式不受检查异常声明的影响。
其他注意事项:
需要注意的是,某些异常仍然可以逃脱lambda 表达式,即使使用建议的解决方案。例如,在计算收集操作期间引发的异常仍会从 lambda 传播出去。
以上是过滤流时如何处理 Java 8 Lambda 表达式中的异常?的详细内容。更多信息请关注PHP中文网其他相关文章!