给定一个 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
中的那些元素?
最佳答案
可以使用 Spliterator
将 Stream
包装到另一个流中。此方法将通过捕获 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/