--- old/src/share/classes/java/util/stream/Streams.java 2013-07-04 00:24:31.994329394 -0700 +++ new/src/share/classes/java/util/stream/Streams.java 2013-07-04 00:24:31.814329397 -0700 @@ -43,7 +43,7 @@ * * @since 1.8 */ -class Streams { +final class Streams { private Streams() { throw new Error("no instances"); @@ -670,4 +670,147 @@ } } } + + abstract static class ConcatSpliterator> + implements Spliterator { + 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 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 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 getComparator() { + if (beforeSplit) + throw new IllegalStateException(); + return bSpliterator.getComparator(); + } + + static class OfRef extends ConcatSpliterator> { + OfRef(Spliterator aSpliterator, Spliterator bSpliterator) { + super(aSpliterator, bSpliterator); + } + } + + private static abstract class OfPrimitive> + extends ConcatSpliterator + implements Spliterator.OfPrimitive { + 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 + implements Spliterator.OfInt { + OfInt(Spliterator.OfInt aSpliterator, Spliterator.OfInt bSpliterator) { + super(aSpliterator, bSpliterator); + } + } + + static class OfLong + extends ConcatSpliterator.OfPrimitive + implements Spliterator.OfLong { + OfLong(Spliterator.OfLong aSpliterator, Spliterator.OfLong bSpliterator) { + super(aSpliterator, bSpliterator); + } + } + + static class OfDouble + extends ConcatSpliterator.OfPrimitive + implements Spliterator.OfDouble { + OfDouble(Spliterator.OfDouble aSpliterator, Spliterator.OfDouble bSpliterator) { + super(aSpliterator, bSpliterator); + } + } + } }