java - 流 : toArray crashing after concat

标签 java java-8 java-stream

我有一些代码如下所示:

Stream a = Streams.from(...).map(...);
Stream b = Streams.from(...);
Stream c = Stream.concat(a, b);
c.toArray();

( Streams.from(Iterable) 从可迭代对象创建流 - 视为 Iterable#stream() 不存在)

最后一行崩溃,但出现异常:

Exception in thread "main" java.lang.IllegalStateException: Accept exceeded fixed size of 266
    at java.util.stream.Nodes$FixedNodeBuilder.accept(Nodes.java:1224)
    at java.util.Iterator.forEachRemaining(Iterator.java:116)
    at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:743)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:576)
    at java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:255)
    at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:438)
    at ... (my code)

266实际上是流a的大小。直播b是 11 个元素。

我做了一些测试。删除map(...)从代码中可以看出它的工作原理。 以下最小示例也适用:

Stream x = Stream.of(1, 2).map(w -> w + 1);
Stream y = Stream.of(3, 4);
Stream z = Stream.concat(x, y);
z.toArray();

此时我非常怀疑我的映射功能,但是这工作得很好:

Object[] a = Streams.from(...).map(...).toArray();
Object[] b = Streams.from(...).toArray();
Object[] c = ArrayUtils.addAll(a, b);

是否有一个流 API 的微妙之处可以解释这种奇怪的行为?

提及该流可能相关 b由一个集合构造而成,当调用映射函数时该集合将被填充。

最佳答案

您的流 b 源集合似乎未正确实现,因为它使用 Collection.spliterator() 的默认实现它假设 Collection 在流操作期间没有被修改(特别是它的 size() 没有改变)。就您而言,这似乎是错误的。

如果没有看到您的集合的完整代码,提出修复建议并不那么容易。如果您的情况可能,您可以在调用 size() 方法时执行初始化,因此在遍历集合之前调用 size() 将返回正确的大小(目前似乎返回0)。另一种方法是重写 spliterator() 方法,如下所示:

public Spliterator<E> spliterator() {
    return Spliterators.spliteratorUnknownSize(this.iterator(), Spliterator.ORDERED);
}

这样,就不会报告 SIZED 特征,并且流管道将不依赖于大小。现在,toArray() 可能会工作得更慢,因为可能需要重新分配数组,但它会正常工作。

关于java - 流 : toArray crashing after concat,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32084205/

相关文章:

java - 更高效的 compareTo 算法?

java - 将 Java 应用程序部署到 Heroku

java - 有没有办法让需要文件参数的命令行程序使用标准输入?

java - Java 8 中如何处理货币?

java - 您将如何对 Java 8 流执行多项操作?

java - 如何在空列表中使用 Java Stream

java - 即使 Libgdx 说它已加载到内存中,声音第一次也不会播放

java - Lambda 表达式如何转换成 Java 字节码

Java8 Groupby 字段和收集对象

java - 从 List<Foo> 到 Map<String, List<Foo>> : looking for a better implementation