检查是否已消耗Java流 [英] Check if java stream has been consumed

查看:60
本文介绍了检查是否已消耗Java流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何检查流实例是否已被使用(意味着已经调用了终端操作,使得对终端操作的任何进一步调用都可能因IllegalStateException: stream has already been operated upon or closed.而失败?

How can I check if a stream instance has been consumed or not (meaning having called a terminal operation such that any further call to a terminal operation may fail with IllegalStateException: stream has already been operated upon or closed.?

理想情况下,我想要一个不消耗流的方法,如果尚未消耗流,则返回一个布尔值false(如果流被消耗而没有从流方法捕获IllegalStateException)(因为使用Exceptions作为控制权)流程昂贵且容易出错,尤其是在使用标准Exceptions时.)

Ideally I want a method that does not consume the stream if it has not yet been consumed, and that returns a boolean false if the stream has been consumed without catching an IllegalStateException from a stream method (because using Exceptions for control flow is expensive and error prone, in particular when using standard Exceptions).

与Iterator中的hasNext()相似的方法,它具有异常抛出和布尔返回行为(尽管没有与next()签订合同).

A method similar to hasNext() in Iterator in the exception throwing and boolean return behavior (though without the contract 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");
   }
}

目标是如果客户端代码在不消耗流的情况下调用此方法,则会尽早失败.

The goal is to fail early if client code calls this method without consuming the stream.

似乎没有办法做到这一点,我必须添加一个try-catch块来调用诸如iterator()之类的任何终端操作,捕获异常并抛出新异常.

It seems there is no method to do that and I'd have to add a try-catch block calling any terminal operation like iterator(), catch an exception and throw a new one.

一个可以接受的答案也可以是没有解决方案",并且有充分的理由说明为什么规范不能添加这种方法(如果存在充分的理由).似乎JDK流通常在其终端方法的开头具有以下代码段:

An acceptable answer can also be "No solution exists" with a good justification of why the specification could not add such a method (if a good justification exists). It seems that the JDK streams usually have this snippets at the start of their terminal methods:

// in AbstractPipeline.java
if (linkedOrConsumed)
    throw new IllegalStateException(MSG_STREAM_LINKED);

因此对于这些流,实现这种方法似乎并不那么困难.

So for those streams, an implementation of such a method would not seem that difficult.

推荐答案

考虑到spliterator(例如)是终端操作,您可以简单地创建一个方法,例如:

Taking into consideration that spliterator (for example) is a terminal operation, you can simply create a method like:

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()));
}

我不知道有什么更好的方法...而用法是:

I don't know of a better way to do it... And usage would be:

Stream<Integer> ints = Stream.of(1, 2, 3, 4)
                                 .filter(x -> x < 3);

YourClass.isConsumed(ints)
         .ifPresent(x -> x.forEachOrdered(System.out::println));

由于我认为不存在返回已消耗的Stream的实际原因,因此我将返回Optional.empty().

Since I don't think there is a practical reason to return an already consumed Stream, I am returning Optional.empty() instead.

这篇关于检查是否已消耗Java流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆