java - 如何在 Java 8 Stream.flatMap(..) 中捕获异常

标签 java exception java-8 java-stream

给定一个 Stream 和一个返回 Stream 作为数据源的不同参数的方法,我正在寻找一种通过 flatMap 合并流的方法(..) 并在执行期间捕获某些 Exceptions

让我们看下面的代码片段:

public class FlatMap {

    public static void main(final String[] args) {
        long count;

        // this might throw an exception
        count = Stream.of(0.2, 0.5, 0.99).flatMap(chance -> getGenerator(chance, 20)).count();

        // trying to catch the exception in flatMap() will not work
        count = Stream.of(0.2, 0.5, 0.99).flatMap(chance -> {
            try {
                return getGenerator(chance, 20);
            } catch (final NullPointerException e) {
                return Stream.empty();
            }
        }).count();

        System.out.println(count);
    }

    // !! we cannot change this method, we simply get a Stream
    static Stream<Object> getGenerator(final double chance, final long limit) {
        return Stream.generate(() -> {
            if (Math.random() < chance) return new Object();
            throw new NullPointerException();
        }).limit(limit);
    }
}

有什么方法可以捕获由 getGenerator(..) 创建的每个 Stream 的异常并简单地抑制 Exception ,将“损坏的”Stream 替换为空的,或者跳过特定生成器 Stream 中的那些元素?

最佳答案

可以使用 SpliteratorStream 包装到另一个流中。此方法将通过捕获 Exception 并保存此状态来保护给定的 Stream:

    static <T> Stream<T> protect(final Stream<T> stream) {
        final Spliterator<T> spliterator = stream.spliterator();
        return StreamSupport.stream(
                new Spliterators.AbstractSpliterator<T>(Long.MAX_VALUE,
                           spliterator.characteristics() & ~Spliterator.SIZED) {

                    private boolean corrupted = false;

                    @Override
                    public boolean tryAdvance(final Consumer<? super T> action) {
                        if (!corrupted) try {
                            return spliterator.tryAdvance(action);
                        } catch (final Exception e) {
                            // we suppress this one, stream ends here
                            corrupted = true;
                        }
                        return false;
                    }
                }, false);
    }

然后我们可以包装我们的Stream方法并安全地将它传递给flatMap(..):

// we protect the stream by a wrapper Stream
count = Stream.of(0.2, 0.5, 0.99)
              .flatMap(chance -> protect(getGenerator(chance, 20)))
              .count();

关于java - 如何在 Java 8 Stream.flatMap(..) 中捕获异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54096105/

相关文章:

java - 将值放在 ConcurrentHashMap 中是否是原子的?

Java序列化测试

java - python 到 Java 校验和计算

exception - F# - 为什么 Seq.map 不传播异常?

javafx - 在 JavaFX 中将堆栈跟踪打印到 Textarea 中

java - 检查每个列表项的语句

java - ArrayBlockingQueue,如果在添加元素时队列已满,则删除队列头

java - 向 map 添加多个地理围栏

c++ - 异常 - VC++2015 CTP Ultimate 中的不正确行为

java - 在 Java 中使用 Optional 和 Streams