src/share/classes/java/util/stream/Streams.java

Print this page
rev 7532 : 8015315: Stream.concat methods
Contributed-by: brian.goetz@oracle.com, henry.jen@oracle.com

*** 41,51 **** * sequential stream can be transformed into a parallel stream by calling the * {@code parallel()} method on the created stream. * * @since 1.8 */ ! class Streams { private Streams() { throw new Error("no instances"); } --- 41,51 ---- * sequential stream can be transformed into a parallel stream by calling the * {@code parallel()} method on the created stream. * * @since 1.8 */ ! final class Streams { private Streams() { throw new Error("no instances"); }
*** 668,673 **** --- 668,816 ---- action.accept(first); count = -1; } } } + + abstract static class ConcatSpliterator<T, T_SPLITR extends Spliterator<T>> + implements Spliterator<T> { + protected final T_SPLITR aSpliterator; + protected final T_SPLITR bSpliterator; + // True when no split has occurred, otherwise false + boolean beforeSplit; + // Never read after splitting + final boolean unsized; + + public ConcatSpliterator(T_SPLITR aSpliterator, T_SPLITR bSpliterator) { + this.aSpliterator = aSpliterator; + this.bSpliterator = bSpliterator; + beforeSplit = true; + // The spliterator is unsized before splitting if a and b are + // sized and the sum of the estimates overflows + unsized = aSpliterator.hasCharacteristics(SIZED) + && aSpliterator.hasCharacteristics(SIZED) + && aSpliterator.estimateSize() + bSpliterator.estimateSize() < 0; + } + + @Override + public T_SPLITR trySplit() { + T_SPLITR ret = beforeSplit ? aSpliterator : (T_SPLITR) bSpliterator.trySplit(); + beforeSplit = false; + return ret; + } + + @Override + public boolean tryAdvance(Consumer<? super T> consumer) { + boolean hasNext; + if (beforeSplit) { + hasNext = aSpliterator.tryAdvance(consumer); + if (!hasNext) { + beforeSplit = false; + hasNext = bSpliterator.tryAdvance(consumer); + } + } + else + hasNext = bSpliterator.tryAdvance(consumer); + return hasNext; + } + + @Override + public void forEachRemaining(Consumer<? super T> consumer) { + if (beforeSplit) + aSpliterator.forEachRemaining(consumer); + bSpliterator.forEachRemaining(consumer); + } + + @Override + public long estimateSize() { + if (beforeSplit) { + // If one or both estimates are Long.MAX_VALUE then the sum + // will either be Long.MAX_VALUE or overflow to a negative value + long size = aSpliterator.estimateSize() + bSpliterator.estimateSize(); + return (size >= 0) ? size : Long.MAX_VALUE; + } + else { + return bSpliterator.estimateSize(); + } + } + + @Override + public int characteristics() { + if (beforeSplit) { + // Concatenation loses DISTINCT and SORTED characteristics + return aSpliterator.characteristics() & bSpliterator.characteristics() + & ~(Spliterator.DISTINCT | Spliterator.SORTED + | (unsized ? Spliterator.SIZED | Spliterator.SUBSIZED : 0)); + } + else { + return bSpliterator.characteristics(); + } + } + + @Override + public Comparator<? super T> getComparator() { + if (beforeSplit) + throw new IllegalStateException(); + return bSpliterator.getComparator(); + } + + static class OfRef<T> extends ConcatSpliterator<T, Spliterator<T>> { + OfRef(Spliterator<T> aSpliterator, Spliterator<T> bSpliterator) { + super(aSpliterator, bSpliterator); + } + } + + private static abstract class OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>> + extends ConcatSpliterator<T, T_SPLITR> + implements Spliterator.OfPrimitive<T, T_CONS, T_SPLITR> { + private OfPrimitive(T_SPLITR aSpliterator, T_SPLITR bSpliterator) { + super(aSpliterator, bSpliterator); + } + + @Override + public boolean tryAdvance(T_CONS action) { + boolean hasNext; + if (beforeSplit) { + hasNext = aSpliterator.tryAdvance(action); + if (!hasNext) { + beforeSplit = false; + hasNext = bSpliterator.tryAdvance(action); + } + } + else + hasNext = bSpliterator.tryAdvance(action); + return hasNext; + } + + @Override + public void forEachRemaining(T_CONS action) { + if (beforeSplit) + aSpliterator.forEachRemaining(action); + bSpliterator.forEachRemaining(action); + } + } + + static class OfInt + extends ConcatSpliterator.OfPrimitive<Integer, IntConsumer, Spliterator.OfInt> + implements Spliterator.OfInt { + OfInt(Spliterator.OfInt aSpliterator, Spliterator.OfInt bSpliterator) { + super(aSpliterator, bSpliterator); + } + } + + static class OfLong + extends ConcatSpliterator.OfPrimitive<Long, LongConsumer, Spliterator.OfLong> + implements Spliterator.OfLong { + OfLong(Spliterator.OfLong aSpliterator, Spliterator.OfLong bSpliterator) { + super(aSpliterator, bSpliterator); + } + } + + static class OfDouble + extends ConcatSpliterator.OfPrimitive<Double, DoubleConsumer, Spliterator.OfDouble> + implements Spliterator.OfDouble { + OfDouble(Spliterator.OfDouble aSpliterator, Spliterator.OfDouble bSpliterator) { + super(aSpliterator, bSpliterator); + } + } + } }