AbstractSpliterator
実装を使用すると私はjava.lang.OutOfMemoryError: Java heap space
を得ました。これは未知のサイズを報告します。Abstract未知のサイズを持つスプリッタの実装はOutOfMemoryErrorをスローします:Javaヒープ領域
この場合、AbstractSpliterator
に拡張されたクラスStreamCollapse
を定義し、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;
}
}
これは正解です。スプライテータ*は、 'SIZED'と' SUBSIZED'特性をクリアする必要があります。さらに、ソーススプライテータの 'estimateSize()'をフィルタスプライテータの推定サイズとして使用することは良いアプローチになります。結局のところ、実際のサイズは0とそのソースサイズの間のどこかになります。これは 'filter'のやり方であり、現在の実装では完全に未知のサイズよりもはるかに優れています。 – Holger
@Holger監査のために私の答えをありがとう。私もあなたの提案を得る。 –