当我使用java.lang.OutOfMemoryError: Java heap space
实施时,我有一个AbstractSpliterator
,报告的大小未知。
在这种情况下,我定义了一个类StreamCollapse
,它扩展了AbstractSpliterator
并合并了tryAdvance()
实现中的一系列相邻元素。它的构造函数将超级构造函数调用为super(Long.MAX_VALUE, source.characteristics())
。
关于API documentation我期望使用Long.MAX_VALUE
表示未知大小。但是,似乎它正试图分配具有该大小的内存。
为什么要分配那个空间?我应该使用什么价值估算大小?
这是一个示例测试:
Stream<Integer> nrs = Stream.of(3, 3, 5, 5, 3, 3, 3, 4, 4, 4 ,5 , 5);
Integer [] expected = {3, 5, 3, 4, 5};
Object[] actual = collapse(nrs).toArray();
assertEquals(actual, expected);
collapse()
方法实现:
static <T> Stream<T> collapse(Stream<T> source) {
return StreamSupport.stream(
new StreamCollapse<T>(source.spliterator()), false);
}
class StreamCollapse<T> extends AbstractSpliterator<T> implements Consumer<T> {
private final Spliterator<T> source;
private T curr = null;
StreamCollapse(Spliterator<T> source) {
super(Long.MAX_VALUE, source.characteristics());
this.source = source;
}
@Override
public boolean tryAdvance(Consumer<? super T> action) {
T prev = curr;
boolean hasNext;
while ((hasNext = source.tryAdvance(this)) && curr.equals(prev)) { }
if(hasNext) action.accept(curr);
return hasNext;
}
@Override
public void accept(T item) {
curr = item;
}
}
答案 0 :(得分:7)
您应该从合成的分裂器中删除特征,例如:
// an unknown spliterator shouldn't having SIZED | SUBSIZED characteristics
// v
super(Long.MAX_VALUE, source.characteristics() & (~(SIZED | SUBSIZED)));
WHEN Spliteartor是SIZED Spliteartor,流将使用Spliterator#getExactSizeIfKnown来创建数组。
如果 estimateSize &gt; =表示在遍历或拆分之前从
estimateSize()
返回的值表示有限大小的特征值,在缺少结构源修改,表示完整遍历将遇到的元素数量的精确计数。
IllegalArgumentException
, IF 并行运行,Stream#toArray会引发Long.MAX_VALUE - 8
。
IF 该流是一个顺序流,Stream#toArray将其内部数组容量增加到 estimateSize 。