Lambda 中的异常( 二 )


- Vavr 
想象一下,我们想要一个收集异常和类的管道 。以下是描述几个构建块的 API 摘录:

Lambda 中的异常

文章插图
它转换为以下代码:
Stream.of("java.lang.String", "ch.frankel.blog.Dummy", "java.util.ArrayList")
.map(CheckedFunction1.liftTry(Class::forName)) // 1
.map(Try::toEither) // 2
.forEach(e -> {
if (e.isLeft()) { // 3
System.out.println("not found:" + e.getLeft().getMessage());
} else {
System.out.println("class:" + e.get().getName());
  1. 将调用包装到 VavrTry中 。
  2. 将 转换Try为Either以保留异常 。如果我们不感兴趣,我们可以使用 anOptional来代替 。
  3. 根据是否Either包含异常left或预期结果right 采取行动 。
 
到目前为止,我们还停留在 Java Streams 的世界中 。它按预期工作,直到forEach看起来并不“好” 。
Vavr 确实提供了自己的Stream类,它模仿 Java StreamAPI 并添加了额外的特性 。让我们用它来重写管道:
var result = Stream.of("java.lang.String", "ch.frankel.blog.Dummy", "java.util.ArrayList")
.map(CheckedFunction1.liftTry(Class::forName))
.map(Try::toEither)
.partition(Either::isLeft) // 1
.map1(left -> left.map(Either::getLeft)) // 2
.map2(right -> right.map(Either::get)); // 3
result._1().forEach(it -> System.out.println("not found: " + it.getMessage())); // 4
result._2().forEach(it -> System.out.println("class: " + it.getName())); // 4
 
  1. Stream将of划分Either为两个的元组Stream 。
  2. 将左侧流从 a Streamof展平Either到 a Streamof Throwable 。
  3. 将右流从 a Streamof展平Either到 a Streamof Class 。
  4. 做我们想做的任何事 。
结论Java 的初始设计大量使用了检查异常 。编程语言的发展证明这不是一个好主意 。
Java 流不能很好地处理已检查的异常 。将后者集成到前者所需的代码看起来不太好 。为了恢复我们期望的流的可读性,我们可以依赖 Apache Commons Lang 。
汇编只代表了问题的一小部分 。我们通常希望对异常采取行动,而不是停止管道或忽略异常 。在这种情况下,我们可以利用 Vavr 库,它提供了一种更实用的方法 。
你可以在GitHub上找到这篇文章的源代码 。




推荐阅读