我如何检查流实例是否已被使用(意味着已经调用了终端操作,使得对终端操作的任何进一步调用都可能失败IllegalStateException: stream has already been operated upon or closed.?
理想情况下,我想要一个不消耗流的方法,如果该流尚未被消耗,则返回一个布尔值false(如果流被消耗而没有IllegalStateException从流方法中捕获)(因为对控制流使用Exception代价很高并且容易出错) ,尤其是在使用标准例外时)。
与hasNext()Iterator中类似的方法,它具有异常抛出和布尔返回行为(尽管没有约定to next())。
例:
public void consume(java.util.function.Consumer<Stream<?>> consumer, Stream<?> stream) {
consumer.accept(stream);
// defensive programming, check state
if (...) {
throw new IllegalStateException("consumer must call terminal operation on stream");
}
}
Run Code Online (Sandbox Code Playgroud)
目标是如果客户端代码在不消耗流的情况下调用此方法,则会尽早失败。
似乎没有办法做到这一点,我必须添加一个try-catch块来调用任何终端操作,例如iterator(),捕获异常并抛出一个新异常。
可以接受的答案也可以是“不存在解决方案”,其中有充分的理由说明为什么规范无法添加这种方法(如果存在良好的理由)。似乎JDK流通常在其终端方法的开头具有以下代码片段:
// in AbstractPipeline.java
if (linkedOrConsumed)
throw new IllegalStateException(MSG_STREAM_LINKED);
Run Code Online (Sandbox Code Playgroud)
因此,对于那些流,实现这种方法似乎并不那么困难。
考虑到spliterator(例如)是终端操作,您可以简单地创建一个方法,例如:
private static <T> Optional<Stream<T>> isConsumed(Stream<T> stream) {
Spliterator<T> spliterator;
try {
spliterator = stream.spliterator();
} catch (IllegalStateException ise) {
return Optional.empty();
}
return Optional.of(StreamSupport.stream(
() -> spliterator,
spliterator.characteristics(),
stream.isParallel()));
}
Run Code Online (Sandbox Code Playgroud)
我不知道有更好的方法......用法是:
Stream<Integer> ints = Stream.of(1, 2, 3, 4)
.filter(x -> x < 3);
YourClass.isConsumed(ints)
.ifPresent(x -> x.forEachOrdered(System.out::println));
Run Code Online (Sandbox Code Playgroud)
由于我认为没有实际原因返回已消耗的 Stream,Optional.empty()因此我将返回。
| 归档时间: |
|
| 查看次数: |
223 次 |
| 最近记录: |