首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java 8流中的聚合运行时异常

Java 8流中的聚合运行时异常
EN

Stack Overflow用户
提问于 2015-05-08 06:27:16
回答 4查看 24.2K关注 0票数 29

假设我有一个抛出运行时异常的方法。我使用Stream对列表中的项调用此方法。

代码语言:javascript
运行
复制
class ABC {

    public void doStuff(MyObject myObj) {
        if (...) {
            throw new IllegalStateException("Fire! Fear! Foes! Awake!");
        }
        // do stuff...
    }

    public void doStuffOnList(List<MyObject> myObjs) {
        try {
            myObjs.stream().forEach(ABC:doStuff);
        } catch(AggregateRuntimeException??? are) {
            ...
        }             
    }
}

现在,我希望处理列表中的所有项,并将各个项目上的任何运行时异常收集到一个“聚合”运行时异常中,该异常将在最后抛出。

在我的实际代码中,我正在进行第三方API调用,这可能会引发运行时异常。我想确保所有项目都已处理完毕,并报告了任何错误。

我可以想出几种方法来破解这个问题,比如捕获并返回异常的map()函数(..shudder.)。但有本土化的方法吗?如果没有,是否有其他方法干净地实现它?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-05-08 07:24:13

在这种简单的情况下,doStuff方法是void,您只关心异常,可以保持简单:

代码语言:javascript
运行
复制
myObjs.stream()
    .flatMap(o -> {
        try {
            ABC.doStuff(o);
            return null;
        } catch (RuntimeException ex) {
            return Stream.of(ex);
        }
    })
    // now a stream of thrown exceptions.
    // can collect them to list or reduce into one exception
    .reduce((ex1, ex2) -> {
        ex1.addSuppressed(ex2);
        return ex1;
    }).ifPresent(ex -> {
        throw ex;
    });

但是,如果您的需求更复杂,并且您更喜欢使用标准库,那么CompletableFuture可以用来表示“成功或失败”(尽管有一些缺陷):

代码语言:javascript
运行
复制
public static void doStuffOnList(List<MyObject> myObjs) {
    myObjs.stream()
            .flatMap(o -> completedFuture(o)
                    .thenAccept(ABC::doStuff)
                    .handle((x, ex) -> ex != null ? Stream.of(ex) : null)
                    .join()
            ).reduce((ex1, ex2) -> {
                ex1.addSuppressed(ex2);
                return ex1;
            }).ifPresent(ex -> {
                throw new RuntimeException(ex);
            });
}
票数 28
EN

Stack Overflow用户

发布于 2015-05-08 07:08:17

Java已经有了一些实现。例如,我找到了更好-java8-monad库。使用它,您可以使用以下样式编写。

假设您想要映射您的值并跟踪所有异常:

代码语言:javascript
运行
复制
public String doStuff(String s) {
    if(s.startsWith("a")) {
        throw new IllegalArgumentException("Incorrect string: "+s);
    }
    return s.trim();
}

让我们有一些投入:

代码语言:javascript
运行
复制
List<String> input = Arrays.asList("aaa", "b", "abc  ", "  qqq  ");

现在我们可以将它们映射到成功的尝试并传递给您的方法,然后分别收集成功处理的数据和失败:

代码语言:javascript
运行
复制
Map<Boolean, List<Try<String>>> result = input.stream()
        .map(Try::successful).map(t -> t.map(this::doStuff))
        .collect(Collectors.partitioningBy(Try::isSuccess));

之后,您可以处理成功的条目:

代码语言:javascript
运行
复制
System.out.println(result.get(true).stream()
    .map(t -> t.orElse(null)).collect(Collectors.joining(",")));

做一些事情,除了所有的例外:

代码语言:javascript
运行
复制
result.get(false).stream().forEach(t -> t.onFailure(System.out::println));

产出如下:

代码语言:javascript
运行
复制
b,qqq
java.lang.IllegalArgumentException: Incorrect string: aaa
java.lang.IllegalArgumentException: Incorrect string: abc  

我个人不喜欢这个库是如何设计的,但它可能会适合你。

下面是一个完整示例的要旨

票数 5
EN

Stack Overflow用户

发布于 2015-05-08 07:05:29

这是一个关于映射到异常的主题的变化。

从您现有的doStuff方法开始。注意,这符合函数接口Consumer<MyObject>

代码语言:javascript
运行
复制
public void doStuff(MyObject myObj) {
    if (...) {
        throw new IllegalStateException("Fire! Fear! Foes! Awake!");
    }
    // do stuff...
}

现在编写一个高阶函数,将其包装起来,并将其转换为一个函数,该函数可能返回或不返回异常。我们希望从flatMap中调用它,所以表示“可能或不可能”的方式是返回包含异常或空流的流。这里我将使用RuntimeException作为异常类型,但当然可以是任何类型。(实际上,在检查异常的情况下使用此技术可能是有用的。)

代码语言:javascript
运行
复制
<T> Function<T,Stream<RuntimeException>> ex(Consumer<T> cons) {
    return t -> {
        try {
            cons.accept(t);
            return Stream.empty();
        } catch (RuntimeException re) {
            return Stream.of(re);
        }
    };
}

现在重写doStuffOnList以便在流中使用它:

代码语言:javascript
运行
复制
void doStuffOnList(List<MyObject> myObjs) {
    List<RuntimeException> exs =
        myObjs.stream()
              .flatMap(ex(this::doStuff))
              .collect(Collectors.toList());
    System.out.println("Exceptions: " + exs);
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30117134

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档