我有一些代码如下:
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
是从一个集合构造的,该集合在调用映射函数时会被填充。
答案 0 :(得分:1)
似乎您的流b
的源集合未正确实现,因为它使用Collection.spliterator()
的默认实现,该实现假定在流操作期间未修改Collection
(特别是其{ {1}}不会改变)。在你的情况下,这似乎是错误的。
如果没有看到您的收藏集的完整代码,提出修复程序就不那么容易了。如果在您的情况下可能,您可以在调用size()
方法时执行初始化,因此在遍历集合之前调用size()
将返回正确的大小(当前它似乎返回0 )。另一种方法是覆盖size()
方法,如下所示:
spliterator()
这样就不会报告public Spliterator<E> spliterator() {
return Spliterators.spliteratorUnknownSize(this.iterator(), Spliterator.ORDERED);
}
特征,并且流管道不会依赖于大小。现在SIZED
可能会运行得更慢,因为阵列重新分配可能是必要的,但它可以正常工作。