jdk/src/share/classes/java/util/stream/Streams.java
changeset 18158 d5a620310f97
parent 18153 644df1dfb3be
child 18820 a87cdd6a8834
equal deleted inserted replaced
18157:ee3bda8e26c6 18158:d5a620310f97
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 package java.util.stream;
    25 package java.util.stream;
    26 
    26 
    27 import java.util.Comparator;
    27 import java.util.Comparator;
    28 import java.util.Iterator;
       
    29 import java.util.Objects;
    28 import java.util.Objects;
    30 import java.util.Spliterator;
    29 import java.util.Spliterator;
    31 import java.util.Spliterators;
    30 import java.util.Spliterators;
    32 import java.util.function.BiFunction;
    31 import java.util.function.BiFunction;
    33 import java.util.function.Consumer;
    32 import java.util.function.Consumer;
    60 
    59 
    61     /**
    60     /**
    62      * An {@code int} range spliterator.
    61      * An {@code int} range spliterator.
    63      */
    62      */
    64     static final class RangeIntSpliterator implements Spliterator.OfInt {
    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
    65         private int from;
    67         private int from;
    66         private final int upTo;
    68         private final int upTo;
    67         private final int step;
    69         // 1 if the range is closed and the last element has not been traversed
    68 
    70         // Otherwise, 0 if the range is open, or is a closed range and all
    69         RangeIntSpliterator(int from, int upTo, int step) {
    71         // elements have been traversed
       
    72         private int last;
       
    73 
       
    74         RangeIntSpliterator(int from, int upTo, boolean closed) {
       
    75             this(from, upTo, closed ? 1 : 0);
       
    76         }
       
    77 
       
    78         private RangeIntSpliterator(int from, int upTo, int last) {
    70             this.from = from;
    79             this.from = from;
    71             this.upTo = upTo;
    80             this.upTo = upTo;
    72             this.step = step;
    81             this.last = last;
    73         }
    82         }
    74 
    83 
    75         @Override
    84         @Override
    76         public boolean tryAdvance(IntConsumer consumer) {
    85         public boolean tryAdvance(IntConsumer consumer) {
    77             boolean hasNext = from < upTo;
    86             final int i = from;
    78             if (hasNext) {
    87             if (i < upTo) {
    79                 consumer.accept(from);
    88                 from++;
    80                 from += step;
    89                 consumer.accept(i);
    81             }
    90                 return true;
    82             return hasNext;
    91             }
       
    92             else if (last > 0) {
       
    93                 last = 0;
       
    94                 consumer.accept(i);
       
    95                 return true;
       
    96             }
       
    97             return false;
    83         }
    98         }
    84 
    99 
    85         @Override
   100         @Override
    86         public void forEachRemaining(IntConsumer consumer) {
   101         public void forEachRemaining(IntConsumer consumer) {
    87             int hUpTo = upTo;
   102             int i = from;
    88             int hStep = step; // hoist accesses and checks from loop
   103             final int hUpTo = upTo;
    89             for (int i = from; i < hUpTo; i += hStep)
   104             int hLast = last;
       
   105             from = upTo;
       
   106             last = 0;
       
   107             while (i < hUpTo) {
       
   108                 consumer.accept(i++);
       
   109             }
       
   110             if (hLast > 0) {
       
   111                 // Last element of closed range
    90                 consumer.accept(i);
   112                 consumer.accept(i);
    91             from = upTo;
   113             }
    92         }
   114         }
    93 
   115 
    94         @Override
   116         @Override
    95         public long estimateSize() {
   117         public long estimateSize() {
    96             int d = upTo - from;
   118             // Ensure ranges of size > Integer.MAX_VALUE report the correct size
    97             return (d / step) + ((d % step == 0) ? 0 : 1);
   119             return ((long) upTo) - from + last;
    98         }
   120         }
    99 
   121 
   100         @Override
   122         @Override
   101         public int characteristics() {
   123         public int characteristics() {
   102             return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED |
   124             return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED |
   109             return null;
   131             return null;
   110         }
   132         }
   111 
   133 
   112         @Override
   134         @Override
   113         public Spliterator.OfInt trySplit() {
   135         public Spliterator.OfInt trySplit() {
   114             return estimateSize() <= 1
   136             long size = estimateSize();
       
   137             return size <= 1
   115                    ? null
   138                    ? null
   116                    : new RangeIntSpliterator(from, from = from + midPoint(), step);
   139                    // Left split always has a half-open range
   117         }
   140                    : new RangeIntSpliterator(from, from = from + splitPoint(size), 0);
   118 
   141         }
   119         private int midPoint() {
   142 
   120             // Size is known to be >= 2
   143         /**
   121             int bisection = (upTo - from) / 2;
   144          * The spliterator size below which the spliterator will be split
   122             // If bisection > step then round down to nearest multiple of step
   145          * at the mid-point to produce balanced splits. Above this size the
   123             // otherwise round up to step
   146          * spliterator will be split at a ratio of
   124             return bisection > step ? bisection - bisection % step : step;
   147          * 1:(RIGHT_BALANCED_SPLIT_RATIO - 1)
       
   148          * to produce right-balanced splits.
       
   149          *
       
   150          * <p>Such splitting ensures that for very large ranges that the left
       
   151          * side of the range will more likely be processed at a lower-depth
       
   152          * than a balanced tree at the expense of a higher-depth for the right
       
   153          * side of the range.
       
   154          *
       
   155          * <p>This is optimized for cases such as IntStream.ints() that is
       
   156          * implemented as range of 0 to Integer.MAX_VALUE but is likely to be
       
   157          * augmented with a limit operation that limits the number of elements
       
   158          * to a count lower than this threshold.
       
   159          */
       
   160         private static final int BALANCED_SPLIT_THRESHOLD = 1 << 24;
       
   161 
       
   162         /**
       
   163          * The split ratio of the left and right split when the spliterator
       
   164          * size is above BALANCED_SPLIT_THRESHOLD.
       
   165          */
       
   166         private static final int RIGHT_BALANCED_SPLIT_RATIO = 1 << 3;
       
   167 
       
   168         private int splitPoint(long size) {
       
   169             int d = (size < BALANCED_SPLIT_THRESHOLD) ? 2 : RIGHT_BALANCED_SPLIT_RATIO;
       
   170             // 2 <= size <= 2^32
       
   171             return (int) (size / d);
   125         }
   172         }
   126     }
   173     }
   127 
   174 
   128     /**
   175     /**
   129      * A {@code long} range spliterator.
   176      * A {@code long} range spliterator.
       
   177      *
       
   178      * This implementation cannot be used for ranges whose size is greater
       
   179      * than Long.MAX_VALUE
   130      */
   180      */
   131     static final class RangeLongSpliterator implements Spliterator.OfLong {
   181     static final class RangeLongSpliterator implements Spliterator.OfLong {
       
   182         // Can never be greater that upTo, this avoids overflow if upper bound
       
   183         // is Long.MAX_VALUE
       
   184         // All elements are traversed if from == upTo & last == 0
   132         private long from;
   185         private long from;
   133         private final long upTo;
   186         private final long upTo;
   134         private final long step;
   187         // 1 if the range is closed and the last element has not been traversed
   135 
   188         // Otherwise, 0 if the range is open, or is a closed range and all
   136         RangeLongSpliterator(long from, long upTo, long step) {
   189         // elements have been traversed
       
   190         private int last;
       
   191 
       
   192         RangeLongSpliterator(long from, long upTo, boolean closed) {
       
   193             this(from, upTo, closed ? 1 : 0);
       
   194         }
       
   195 
       
   196         private RangeLongSpliterator(long from, long upTo, int last) {
       
   197             assert upTo - from + last > 0;
   137             this.from = from;
   198             this.from = from;
   138             this.upTo = upTo;
   199             this.upTo = upTo;
   139             this.step = step;
   200             this.last = last;
   140         }
   201         }
   141 
   202 
   142         @Override
   203         @Override
   143         public boolean tryAdvance(LongConsumer consumer) {
   204         public boolean tryAdvance(LongConsumer consumer) {
   144             boolean hasNext = from < upTo;
   205             final long i = from;
   145             if (hasNext) {
   206             if (i < upTo) {
   146                 consumer.accept(from);
   207                 from++;
   147                 from += step;
   208                 consumer.accept(i);
   148             }
   209                 return true;
   149             return hasNext;
   210             }
       
   211             else if (last > 0) {
       
   212                 last = 0;
       
   213                 consumer.accept(i);
       
   214                 return true;
       
   215             }
       
   216             return false;
   150         }
   217         }
   151 
   218 
   152         @Override
   219         @Override
   153         public void forEachRemaining(LongConsumer consumer) {
   220         public void forEachRemaining(LongConsumer consumer) {
   154             long hUpTo = upTo;
   221             long i = from;
   155             long hStep = step; // hoist accesses and checks from loop
   222             final long hUpTo = upTo;
   156             for (long i = from; i < hUpTo; i += hStep)
   223             int hLast = last;
       
   224             from = upTo;
       
   225             last = 0;
       
   226             while (i < hUpTo) {
       
   227                 consumer.accept(i++);
       
   228             }
       
   229             if (hLast > 0) {
       
   230                 // Last element of closed range
   157                 consumer.accept(i);
   231                 consumer.accept(i);
   158             from = upTo;
   232             }
   159         }
   233         }
   160 
   234 
   161         @Override
   235         @Override
   162         public long estimateSize() {
   236         public long estimateSize() {
   163             long d = upTo - from;
   237             return upTo - from + last;
   164             return (d / step) + ((d % step == 0) ? 0 : 1);
       
   165         }
   238         }
   166 
   239 
   167         @Override
   240         @Override
   168         public int characteristics() {
   241         public int characteristics() {
   169             return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED |
   242             return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED |
   176             return null;
   249             return null;
   177         }
   250         }
   178 
   251 
   179         @Override
   252         @Override
   180         public Spliterator.OfLong trySplit() {
   253         public Spliterator.OfLong trySplit() {
   181             return estimateSize() <= 1
   254             long size = estimateSize();
       
   255             return size <= 1
   182                    ? null
   256                    ? null
   183                    : new RangeLongSpliterator(from, from = from + midPoint(), step);
   257                    // Left split always has a half-open range
   184         }
   258                    : new RangeLongSpliterator(from, from = from + splitPoint(size), 0);
   185 
   259         }
   186         private long midPoint() {
   260 
   187             // Size is known to be >= 2
   261         /**
   188             long bisection = (upTo - from) / 2;
   262          * The spliterator size below which the spliterator will be split
   189             // If bisection > step then round down to nearest multiple of step
   263          * at the mid-point to produce balanced splits. Above this size the
   190             // otherwise round up to step
   264          * spliterator will be split at a ratio of
   191             return bisection > step ? bisection - bisection % step : step;
   265          * 1:(RIGHT_BALANCED_SPLIT_RATIO - 1)
       
   266          * to produce right-balanced splits.
       
   267          *
       
   268          * <p>Such splitting ensures that for very large ranges that the left
       
   269          * side of the range will more likely be processed at a lower-depth
       
   270          * than a balanced tree at the expense of a higher-depth for the right
       
   271          * side of the range.
       
   272          *
       
   273          * <p>This is optimized for cases such as LongStream.longs() that is
       
   274          * implemented as range of 0 to Long.MAX_VALUE but is likely to be
       
   275          * augmented with a limit operation that limits the number of elements
       
   276          * to a count lower than this threshold.
       
   277          */
       
   278         private static final long BALANCED_SPLIT_THRESHOLD = 1 << 24;
       
   279 
       
   280         /**
       
   281          * The split ratio of the left and right split when the spliterator
       
   282          * size is above BALANCED_SPLIT_THRESHOLD.
       
   283          */
       
   284         private static final long RIGHT_BALANCED_SPLIT_RATIO = 1 << 3;
       
   285 
       
   286         private long splitPoint(long size) {
       
   287             long d = (size < BALANCED_SPLIT_THRESHOLD) ? 2 : RIGHT_BALANCED_SPLIT_RATIO;
       
   288             // 2 <= size <= Long.MAX_VALUE
       
   289             return size / d;
   192         }
   290         }
   193     }
   291     }
   194 
   292 
   195     private static abstract class AbstractStreamBuilderImpl<T, S extends Spliterator<T>> implements Spliterator<T> {
   293     private static abstract class AbstractStreamBuilderImpl<T, S extends Spliterator<T>> implements Spliterator<T> {
   196         // >= 0 when building, < 0 when built
   294         // >= 0 when building, < 0 when built