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

ben*_*nez 6 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法捕获由每个人Stream创建的例外getGenerator(..)并简单地抑制Exception,用Stream空的替换"损坏的" 或跳过特定生成器中的那些元素Stream

ETO*_*ETO 0

尝试这个:

static <T> Supplier<T> getOrNull(Supplier<T> supplier) {
    return () -> {
        try {
            return supplier.get();
        } catch (Throwable e) {
            return null;
        }
    };
}

static Stream<Object> getGenerator(final double chance, final long limit) {
    return Stream.generate(
                      getOrNull(
                          () -> {
                              if (Math.random() < chance) return new Object();
                              throw new NullPointerException(); 
                              // You can throw any exception here
                          })) 
                .limit(limit)
                .filter(Objects::isNull);
}
Run Code Online (Sandbox Code Playgroud)

然后只需调用getGenerator

count = Stream.of(0.2, 0.5, 0.99)
              .flatMap(chance -> getGenerator(chance, 20))
              .count();
Run Code Online (Sandbox Code Playgroud)