一尘不染

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

java

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

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 ..
)。但是,有没有一种本机的方法可以做到这一点?如果没有,还有另一种方法可以完全实现它吗?


阅读 203

收藏
2020-12-03

共1个答案

一尘不染

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

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则可以代表“成功或失败”(尽管有一些缺陷):

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);
            });
}
2020-12-03