【问题标题】:Stream IllegalStateException流非法状态异常
【发布时间】:2019-04-15 08:52:59
【问题描述】:

我遇到了这个错误,不知道如何调试它。问题的总结是我必须得到一个流的最小值和最大值。我不能使用 Collections 并且流必须是可并行的。此外,流是一个参数,因此它不能被复制。我不是在寻求解决方案,而是错误的含义。

class MinMax {
    final int min, max;

    static Optional<MinMax> findMinMax(Stream<Integer> instream) {
        if(instream.count() > 0) {
            Optional<MinMax> ans = instream.map(x -> {return new MinMax(x,x);}).reduce((x, y) -> {
                Integer max = x.max;
                Integer min = x.min;
                if (y.min < min){
                    min = y.min;
                } 
                if (y.max > max) {
                    max = y.max;
                }
                return new MinMax(min, max);
            });
            return ans;
        } else {
            return Optional.empty();
        }
    }

    public MinMax(int min, int max) {
        this.min = min;
        this.max = max;
    }
    @Override
    public String toString() {
        return min + ", " + max;
    }
}

线程“main”java.lang.IllegalStateException 中的异常:流已被操作或关闭 在 java.base/java.util.stream.AbstractPipeline.(AbstractPipeline.java:203) 在 java.base/java.util.stream.ReferencePipeline.(ReferencePipeline.java:94) 在 java.base/java.util.stream.ReferencePipeline$StatelessOp.(ReferencePipeline.java:696) 在 java.base/java.util.stream.ReferencePipeline$3.(ReferencePipeline.java:189) 在 java.base/java.util.stream.ReferencePipeline.map(ReferencePipeline.java:188) 在 MinMax.findMinMax(MinMax.java:11) 在 Main.main(MinMax.java:46)

【问题讨论】:

  • 您是否为同一个 Stream 多次调用 findMinMax
  • “流已经被操作”。您使用了两次相同的流。
  • 附带说明,.map(x -&gt; {return new MinMax(x,x);}) 是不必要的冗长。您可以改用.map(x -&gt; new MinMax(x,x))。除此之外,虽然基于 Reduction 的解决方案简单且正确,但基于 collect 的解决方案对于大流可能更有效,例如 this answer 末尾显示的 SummaryStatistics 实现。

标签: java java-stream illegalstateexception


【解决方案1】:

使用intstream.count() 关闭流(因为它需要处理整个流以便计算元素的数量)。但是,您的检查是完全不必要的,因为它已经返回了一个可选的,如果流是空的。

【讨论】:

  • 处理流和“关闭”它是两个不同的操作,不应混淆。 count() 处理 Stream,使其无法使用,但不会关闭它。
  • 那么在流的上下文中关闭是什么意思?
  • 调用close() 方法。请参阅the class documentation:“流有一个BaseStream.close() 方法并实现AutoCloseable,但几乎所有流实例实际上不需要在使用后关闭。通常,只有源为 IO 通道的流(例如 Files.lines(Path, Charset) 返回的流)才需要关闭。大多数流由集合、数组或生成函数支持,不需要特殊的资源管理。
【解决方案2】:

在 Java 8 中,每个 Stream 都是一次性数据序列,支持管道中的多个 I/O 操作。

管道操作结束后,流实例被消耗并关闭。

如果您尝试在代码的另一部分再次使用相同的流,您将得到java.lang.IllegalStateException: stream has already been operated upon or closed

在您的代码中,您使用了两次: - instream.count()instream.map()

【讨论】:

    猜你喜欢
    • 2013-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-05
    • 2017-12-06
    • 1970-01-01
    • 2017-08-09
    相关资源
    最近更新 更多