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


  26 
  27 import java.util.Comparator;
  28 import java.util.Objects;
  29 import java.util.Spliterator;
  30 import java.util.Spliterators;
  31 import java.util.function.BiFunction;
  32 import java.util.function.Consumer;
  33 import java.util.function.DoubleConsumer;
  34 import java.util.function.IntConsumer;
  35 import java.util.function.LongConsumer;
  36 
  37 /**
  38  * Utility methods for operating on and creating streams.
  39  *
  40  * <p>Unless otherwise stated, streams are created as sequential streams.  A
  41  * sequential stream can be transformed into a parallel stream by calling the
  42  * {@code parallel()} method on the created stream.
  43  *
  44  * @since 1.8
  45  */
  46 class Streams {
  47 
  48     private Streams() {
  49         throw new Error("no instances");
  50     }
  51 
  52     /**
  53      * An object instance representing no value, that cannot be an actual
  54      * data element of a stream.  Used when processing streams that can contain
  55      * {@code null} elements to distinguish between a {@code null} value and no
  56      * value.
  57      */
  58     static final Object NONE = new Object();
  59 
  60     /**
  61      * An {@code int} range spliterator.
  62      */
  63     static final class RangeIntSpliterator implements Spliterator.OfInt {
  64         // Can never be greater that upTo, this avoids overflow if upper bound
  65         // is Integer.MAX_VALUE
  66         // All elements are traversed if from == upTo & last == 0


 650         // count == -1 for no elements
 651         // count == -2 for one element held by first
 652 
 653         @Override
 654         public boolean tryAdvance(DoubleConsumer action) {
 655             if (count == -2) {
 656                 action.accept(first);
 657                 count = -1;
 658                 return true;
 659             }
 660             else {
 661                 return false;
 662             }
 663         }
 664 
 665         @Override
 666         public void forEachRemaining(DoubleConsumer action) {
 667             if (count == -2) {
 668                 action.accept(first);
 669                 count = -1;















































































































































 670             }
 671         }
 672     }
 673 }


  26 
  27 import java.util.Comparator;
  28 import java.util.Objects;
  29 import java.util.Spliterator;
  30 import java.util.Spliterators;
  31 import java.util.function.BiFunction;
  32 import java.util.function.Consumer;
  33 import java.util.function.DoubleConsumer;
  34 import java.util.function.IntConsumer;
  35 import java.util.function.LongConsumer;
  36 
  37 /**
  38  * Utility methods for operating on and creating streams.
  39  *
  40  * <p>Unless otherwise stated, streams are created as sequential streams.  A
  41  * sequential stream can be transformed into a parallel stream by calling the
  42  * {@code parallel()} method on the created stream.
  43  *
  44  * @since 1.8
  45  */
  46 final class Streams {
  47 
  48     private Streams() {
  49         throw new Error("no instances");
  50     }
  51 
  52     /**
  53      * An object instance representing no value, that cannot be an actual
  54      * data element of a stream.  Used when processing streams that can contain
  55      * {@code null} elements to distinguish between a {@code null} value and no
  56      * value.
  57      */
  58     static final Object NONE = new Object();
  59 
  60     /**
  61      * An {@code int} range spliterator.
  62      */
  63     static final class RangeIntSpliterator implements Spliterator.OfInt {
  64         // Can never be greater that upTo, this avoids overflow if upper bound
  65         // is Integer.MAX_VALUE
  66         // All elements are traversed if from == upTo & last == 0


 650         // count == -1 for no elements
 651         // count == -2 for one element held by first
 652 
 653         @Override
 654         public boolean tryAdvance(DoubleConsumer action) {
 655             if (count == -2) {
 656                 action.accept(first);
 657                 count = -1;
 658                 return true;
 659             }
 660             else {
 661                 return false;
 662             }
 663         }
 664 
 665         @Override
 666         public void forEachRemaining(DoubleConsumer action) {
 667             if (count == -2) {
 668                 action.accept(first);
 669                 count = -1;
 670             }
 671         }
 672     }
 673 
 674     abstract static class ConcatSpliterator<T, T_SPLITR extends Spliterator<T>>
 675             implements Spliterator<T> {
 676         protected final T_SPLITR aSpliterator;
 677         protected final T_SPLITR bSpliterator;
 678         // True when no split has occurred, otherwise false
 679         boolean beforeSplit;
 680         // Never read after splitting
 681         final boolean unsized;
 682 
 683         public ConcatSpliterator(T_SPLITR aSpliterator, T_SPLITR bSpliterator) {
 684             this.aSpliterator = aSpliterator;
 685             this.bSpliterator = bSpliterator;
 686             beforeSplit = true;
 687             // The spliterator is unsized before splitting if a and b are
 688             // sized and the sum of the estimates overflows
 689             unsized = aSpliterator.hasCharacteristics(SIZED)
 690                       && aSpliterator.hasCharacteristics(SIZED)
 691                       && aSpliterator.estimateSize() + bSpliterator.estimateSize() < 0;
 692         }
 693 
 694         @Override
 695         public T_SPLITR trySplit() {
 696             T_SPLITR ret = beforeSplit ? aSpliterator : (T_SPLITR) bSpliterator.trySplit();
 697             beforeSplit = false;
 698             return ret;
 699         }
 700 
 701         @Override
 702         public boolean tryAdvance(Consumer<? super T> consumer) {
 703             boolean hasNext;
 704             if (beforeSplit) {
 705                 hasNext = aSpliterator.tryAdvance(consumer);
 706                 if (!hasNext) {
 707                     beforeSplit = false;
 708                     hasNext = bSpliterator.tryAdvance(consumer);
 709                 }
 710             }
 711             else
 712                 hasNext = bSpliterator.tryAdvance(consumer);
 713             return hasNext;
 714         }
 715 
 716         @Override
 717         public void forEachRemaining(Consumer<? super T> consumer) {
 718             if (beforeSplit)
 719                 aSpliterator.forEachRemaining(consumer);
 720             bSpliterator.forEachRemaining(consumer);
 721         }
 722 
 723         @Override
 724         public long estimateSize() {
 725             if (beforeSplit) {
 726                 // If one or both estimates are Long.MAX_VALUE then the sum
 727                 // will either be Long.MAX_VALUE or overflow to a negative value
 728                 long size = aSpliterator.estimateSize() + bSpliterator.estimateSize();
 729                 return (size >= 0) ? size : Long.MAX_VALUE;
 730             }
 731             else {
 732                 return bSpliterator.estimateSize();
 733             }
 734         }
 735 
 736         @Override
 737         public int characteristics() {
 738             if (beforeSplit) {
 739                 // Concatenation loses DISTINCT and SORTED characteristics
 740                 return aSpliterator.characteristics() & bSpliterator.characteristics()
 741                        & ~(Spliterator.DISTINCT | Spliterator.SORTED
 742                            | (unsized ? Spliterator.SIZED | Spliterator.SUBSIZED : 0));
 743             }
 744             else {
 745                 return bSpliterator.characteristics();
 746             }
 747         }
 748 
 749         @Override
 750         public Comparator<? super T> getComparator() {
 751             if (beforeSplit)
 752                 throw new IllegalStateException();
 753             return bSpliterator.getComparator();
 754         }
 755 
 756         static class OfRef<T> extends ConcatSpliterator<T, Spliterator<T>> {
 757             OfRef(Spliterator<T> aSpliterator, Spliterator<T> bSpliterator) {
 758                 super(aSpliterator, bSpliterator);
 759             }
 760         }
 761 
 762         private static abstract class OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
 763                 extends ConcatSpliterator<T, T_SPLITR>
 764                 implements Spliterator.OfPrimitive<T, T_CONS, T_SPLITR> {
 765             private OfPrimitive(T_SPLITR aSpliterator, T_SPLITR bSpliterator) {
 766                 super(aSpliterator, bSpliterator);
 767             }
 768 
 769             @Override
 770             public boolean tryAdvance(T_CONS action) {
 771                 boolean hasNext;
 772                 if (beforeSplit) {
 773                     hasNext = aSpliterator.tryAdvance(action);
 774                     if (!hasNext) {
 775                         beforeSplit = false;
 776                         hasNext = bSpliterator.tryAdvance(action);
 777                     }
 778                 }
 779                 else
 780                     hasNext = bSpliterator.tryAdvance(action);
 781                 return hasNext;
 782             }
 783 
 784             @Override
 785             public void forEachRemaining(T_CONS action) {
 786                 if (beforeSplit)
 787                     aSpliterator.forEachRemaining(action);
 788                 bSpliterator.forEachRemaining(action);
 789             }
 790         }
 791 
 792         static class OfInt
 793                 extends ConcatSpliterator.OfPrimitive<Integer, IntConsumer, Spliterator.OfInt>
 794                 implements Spliterator.OfInt {
 795             OfInt(Spliterator.OfInt aSpliterator, Spliterator.OfInt bSpliterator) {
 796                 super(aSpliterator, bSpliterator);
 797             }
 798         }
 799 
 800         static class OfLong
 801                 extends ConcatSpliterator.OfPrimitive<Long, LongConsumer, Spliterator.OfLong>
 802                 implements Spliterator.OfLong {
 803             OfLong(Spliterator.OfLong aSpliterator, Spliterator.OfLong bSpliterator) {
 804                 super(aSpliterator, bSpliterator);
 805             }
 806         }
 807 
 808         static class OfDouble
 809                 extends ConcatSpliterator.OfPrimitive<Double, DoubleConsumer, Spliterator.OfDouble>
 810                 implements Spliterator.OfDouble {
 811             OfDouble(Spliterator.OfDouble aSpliterator, Spliterator.OfDouble bSpliterator) {
 812                 super(aSpliterator, bSpliterator);
 813             }
 814         }
 815     }
 816 }