1 /*
   2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.util.stream;
  26 
  27 import java.util.Comparator;
  28 import java.util.Objects;
  29 import java.util.Spliterator;
  30 import java.util.concurrent.ConcurrentHashMap;
  31 import java.util.concurrent.atomic.AtomicLong;
  32 import java.util.function.BooleanSupplier;
  33 import java.util.function.Consumer;
  34 import java.util.function.DoubleConsumer;
  35 import java.util.function.DoubleSupplier;
  36 import java.util.function.IntConsumer;
  37 import java.util.function.IntSupplier;
  38 import java.util.function.LongConsumer;
  39 import java.util.function.LongSupplier;
  40 import java.util.function.Supplier;
  41 
  42 /**
  43  * Spliterator implementations for wrapping and delegating spliterators, used
  44  * in the implementation of the {@link Stream#spliterator()} method.
  45  *
  46  * @since 1.8
  47  */
  48 class StreamSpliterators {
  49 
  50     /**
  51      * Abstract wrapping spliterator that binds to the spliterator of a
  52      * pipeline helper on first operation.
  53      *
  54      * <p>This spliterator is not late-binding and will bind to the source
  55      * spliterator when first operated on.
  56      *
  57      * <p>A wrapping spliterator produced from a sequential stream
  58      * cannot be split if there are stateful operations present.
  59      */
  60     private abstract static class AbstractWrappingSpliterator<P_IN, P_OUT,
  61                                                               T_BUFFER extends AbstractSpinedBuffer>
  62             implements Spliterator<P_OUT> {
  63 
  64         // @@@ Detect if stateful operations are present or not
  65         //     If not then can split otherwise cannot
  66 
  67         /**
  68          * True if this spliterator supports splitting
  69          */
  70         final boolean isParallel;
  71 
  72         final PipelineHelper<P_OUT> ph;
  73 
  74         /**
  75          * Supplier for the source spliterator.  Client provides either a
  76          * spliterator or a supplier.
  77          */
  78         private Supplier<Spliterator<P_IN>> spliteratorSupplier;
  79 
  80         /**
  81          * Source spliterator.  Either provided from client or obtained from
  82          * supplier.
  83          */
  84         Spliterator<P_IN> spliterator;
  85 
  86         /**
  87          * Sink chain for the downstream stages of the pipeline, ultimately
  88          * leading to the buffer. Used during partial traversal.
  89          */
  90         Sink<P_IN> bufferSink;
  91 
  92         /**
  93          * A function that advances one element of the spliterator, pushing
  94          * it to bufferSink.  Returns whether any elements were processed.
  95          * Used during partial traversal.
  96          */
  97         BooleanSupplier pusher;
  98 
  99         /** Next element to consume from the buffer, used during partial traversal */
 100         long nextToConsume;
 101 
 102         /** Buffer into which elements are pushed.  Used during partial traversal. */
 103         T_BUFFER buffer;
 104 
 105         /**
 106          * True if full traversal has occurred (with possible cancelation).
 107          * If doing a partial traversal, there may be still elements in buffer.
 108          */
 109         boolean finished;
 110 
 111         /**
 112          * Construct an AbstractWrappingSpliterator from a
 113          * {@code Supplier<Spliterator>}.
 114          */
 115         AbstractWrappingSpliterator(PipelineHelper<P_OUT> ph,
 116                                     Supplier<Spliterator<P_IN>> spliteratorSupplier,
 117                                     boolean parallel) {
 118             this.ph = ph;
 119             this.spliteratorSupplier = spliteratorSupplier;
 120             this.spliterator = null;
 121             this.isParallel = parallel;
 122         }
 123 
 124         /**
 125          * Construct an AbstractWrappingSpliterator from a
 126          * {@code Spliterator}.
 127          */
 128         AbstractWrappingSpliterator(PipelineHelper<P_OUT> ph,
 129                                     Spliterator<P_IN> spliterator,
 130                                     boolean parallel) {
 131             this.ph = ph;
 132             this.spliteratorSupplier = null;
 133             this.spliterator = spliterator;
 134             this.isParallel = parallel;
 135         }
 136 
 137         /**
 138          * Called before advancing to set up spliterator, if needed.
 139          */
 140         final void init() {
 141             if (spliterator == null) {
 142                 spliterator = spliteratorSupplier.get();
 143                 spliteratorSupplier = null;
 144             }
 145         }
 146 
 147         /**
 148          * Get an element from the source, pushing it into the sink chain,
 149          * setting up the buffer if needed
 150          * @return whether there are elements to consume from the buffer
 151          */
 152         final boolean doAdvance() {
 153             if (buffer == null) {
 154                 if (finished)
 155                     return false;
 156 
 157                 init();
 158                 initPartialTraversalState();
 159                 initPusher();
 160                 nextToConsume = 0;
 161                 bufferSink.begin(spliterator.getExactSizeIfKnown());
 162                 return fillBuffer();
 163             }
 164             else {
 165                 ++nextToConsume;
 166                 boolean hasNext = nextToConsume < buffer.count();
 167                 if (!hasNext) {
 168                     nextToConsume = 0;
 169                     buffer.clear();
 170                     hasNext = fillBuffer();
 171                 }
 172                 return hasNext;
 173             }
 174         }
 175 
 176         /**
 177          * Invokes the shape-specific constructor with the provided arguments
 178          * and returns the result.
 179          */
 180         abstract AbstractWrappingSpliterator<P_IN, P_OUT, T_BUFFER> wrap(Spliterator<P_IN> s);
 181 
 182         /**
 183          * Initializes buffer, sink chain, and pusher for a shape-specific
 184          * implementation.
 185          */
 186         abstract void initPartialTraversalState();
 187 
 188         void initPusher() {
 189             pusher = () -> spliterator.tryAdvance(bufferSink);
 190         }
 191 
 192         @Override
 193         public Spliterator<P_OUT> trySplit() {
 194             if (isParallel && !finished) {
 195                 init();
 196 
 197                 Spliterator<P_IN> split = spliterator.trySplit();
 198                 if (split == null)
 199                     return null;
 200                 AbstractWrappingSpliterator<P_IN, P_OUT, T_BUFFER> prefix = wrap(split);
 201                 if (buffer != null) {
 202                     prefix.buffer = buffer;
 203                     prefix.bufferSink = bufferSink;
 204                     prefix.nextToConsume = nextToConsume;
 205                     prefix.initPusher();
 206                     buffer = null;
 207                 }
 208                 return prefix;
 209             }
 210             else
 211                 return null;
 212         }
 213 
 214         /**
 215          * If the buffer is empty, push elements into the sink chain until
 216          * the source is empty or cancellation is requested.
 217          * @return whether there are elements to consume from the buffer
 218          */
 219         private boolean fillBuffer() {
 220             while (buffer.count() == 0) {
 221                 if (bufferSink.cancellationRequested() || !pusher.getAsBoolean()) {
 222                     if (finished)
 223                         return false;
 224                     else {
 225                         bufferSink.end(); // might trigger more elements
 226                         finished = true;
 227                     }
 228                 }
 229             }
 230             return true;
 231         }
 232 
 233         @Override
 234         public final long estimateSize() {
 235             init();
 236             // Use the estimate of the wrapped spliterator
 237             // Note this may not be accurate if there are filter/flatMap
 238             // operations filtering or adding elements to the stream
 239             return spliterator.estimateSize();
 240         }
 241 
 242         @Override
 243         public final long getExactSizeIfKnown() {
 244             init();
 245             return StreamOpFlag.SIZED.isKnown(ph.getStreamAndOpFlags())
 246                    ? spliterator.getExactSizeIfKnown()
 247                    : -1;
 248         }
 249 
 250         @Override
 251         public final int characteristics() {
 252             init();
 253 
 254             // Get the characteristics from the pipeline
 255             int c = StreamOpFlag.toCharacteristics(StreamOpFlag.toStreamFlags(ph.getStreamAndOpFlags()));
 256 
 257             // Mask off the size and uniform characteristics and replace with
 258             // those of the spliterator
 259             // Note that a non-uniform spliterator can change from something
 260             // with an exact size to an estimate for a sub-split, for example
 261             // with HashSet where the size is known at the top level spliterator
 262             // but for sub-splits only an estimate is known
 263             if ((c & Spliterator.SIZED) != 0) {
 264                 c &= ~(Spliterator.SIZED | Spliterator.SUBSIZED);
 265                 c |= (spliterator.characteristics() & (Spliterator.SIZED | Spliterator.SUBSIZED));
 266             }
 267 
 268             return c;
 269         }
 270 
 271         @Override
 272         public Comparator<? super P_OUT> getComparator() {
 273             if (!hasCharacteristics(SORTED))
 274                 throw new IllegalStateException();
 275             return null;
 276         }
 277 
 278         @Override
 279         public final String toString() {
 280             return String.format("%s[%s]", getClass().getName(), spliterator);
 281         }
 282     }
 283 
 284     static final class WrappingSpliterator<P_IN, P_OUT>
 285             extends AbstractWrappingSpliterator<P_IN, P_OUT, SpinedBuffer<P_OUT>> {
 286 
 287         WrappingSpliterator(PipelineHelper<P_OUT> ph,
 288                             Supplier<Spliterator<P_IN>> supplier,
 289                             boolean parallel) {
 290             super(ph, supplier, parallel);
 291         }
 292 
 293         WrappingSpliterator(PipelineHelper<P_OUT> ph,
 294                             Spliterator<P_IN> spliterator,
 295                             boolean parallel) {
 296             super(ph, spliterator, parallel);
 297         }
 298 
 299         @Override
 300         WrappingSpliterator<P_IN, P_OUT> wrap(Spliterator<P_IN> s) {
 301             return new WrappingSpliterator<>(ph, s, isParallel);
 302         }
 303 
 304         @Override
 305         void initPartialTraversalState() {
 306             SpinedBuffer<P_OUT> b = new SpinedBuffer<>();
 307             buffer = b;
 308             bufferSink = ph.wrapSink(b::accept);
 309         }
 310 
 311         @Override
 312         public boolean tryAdvance(Consumer<? super P_OUT> consumer) {
 313             Objects.requireNonNull(consumer);
 314             boolean hasNext = doAdvance();
 315             if (hasNext)
 316                 consumer.accept(buffer.get(nextToConsume));
 317             return hasNext;
 318         }
 319 
 320         @Override
 321         public void forEachRemaining(Consumer<? super P_OUT> consumer) {
 322             if (buffer == null && !finished) {
 323                 Objects.requireNonNull(consumer);
 324                 init();
 325 
 326                 ph.wrapAndCopyInto((Sink<P_OUT>) consumer::accept, spliterator);
 327                 finished = true;
 328             }
 329             else {
 330                 do { } while (tryAdvance(consumer));
 331             }
 332         }
 333     }
 334 
 335     static final class IntWrappingSpliterator<P_IN>
 336             extends AbstractWrappingSpliterator<P_IN, Integer, SpinedBuffer.OfInt>
 337             implements Spliterator.OfInt {
 338 
 339         IntWrappingSpliterator(PipelineHelper<Integer> ph,
 340                                Supplier<Spliterator<P_IN>> supplier,
 341                                boolean parallel) {
 342             super(ph, supplier, parallel);
 343         }
 344 
 345         IntWrappingSpliterator(PipelineHelper<Integer> ph,
 346                                Spliterator<P_IN> spliterator,
 347                                boolean parallel) {
 348             super(ph, spliterator, parallel);
 349         }
 350 
 351         @Override
 352         AbstractWrappingSpliterator<P_IN, Integer, SpinedBuffer.OfInt> wrap(Spliterator<P_IN> s) {
 353             return new IntWrappingSpliterator<>(ph, s, isParallel);
 354         }
 355 
 356         @Override
 357         void initPartialTraversalState() {
 358             SpinedBuffer.OfInt b = new SpinedBuffer.OfInt();
 359             buffer = b;
 360             bufferSink = ph.wrapSink((Sink.OfInt) b::accept);
 361         }
 362 
 363         @Override
 364         public Spliterator.OfInt trySplit() {
 365             return (Spliterator.OfInt) super.trySplit();
 366         }
 367 
 368         @Override
 369         public boolean tryAdvance(IntConsumer consumer) {
 370             Objects.requireNonNull(consumer);
 371             boolean hasNext = doAdvance();
 372             if (hasNext)
 373                 consumer.accept(buffer.get(nextToConsume));
 374             return hasNext;
 375         }
 376 
 377         @Override
 378         public void forEachRemaining(IntConsumer consumer) {
 379             if (buffer == null && !finished) {
 380                 Objects.requireNonNull(consumer);
 381                 init();
 382 
 383                 ph.wrapAndCopyInto((Sink.OfInt) consumer::accept, spliterator);
 384                 finished = true;
 385             }
 386             else {
 387                 do { } while (tryAdvance(consumer));
 388             }
 389         }
 390     }
 391 
 392     static final class LongWrappingSpliterator<P_IN>
 393             extends AbstractWrappingSpliterator<P_IN, Long, SpinedBuffer.OfLong>
 394             implements Spliterator.OfLong {
 395 
 396         LongWrappingSpliterator(PipelineHelper<Long> ph,
 397                                 Supplier<Spliterator<P_IN>> supplier,
 398                                 boolean parallel) {
 399             super(ph, supplier, parallel);
 400         }
 401 
 402         LongWrappingSpliterator(PipelineHelper<Long> ph,
 403                                 Spliterator<P_IN> spliterator,
 404                                 boolean parallel) {
 405             super(ph, spliterator, parallel);
 406         }
 407 
 408         @Override
 409         AbstractWrappingSpliterator<P_IN, Long, SpinedBuffer.OfLong> wrap(Spliterator<P_IN> s) {
 410             return new LongWrappingSpliterator<>(ph, s, isParallel);
 411         }
 412 
 413         @Override
 414         void initPartialTraversalState() {
 415             SpinedBuffer.OfLong b = new SpinedBuffer.OfLong();
 416             buffer = b;
 417             bufferSink = ph.wrapSink((Sink.OfLong) b::accept);
 418         }
 419 
 420         @Override
 421         public Spliterator.OfLong trySplit() {
 422             return (Spliterator.OfLong) super.trySplit();
 423         }
 424 
 425         @Override
 426         public boolean tryAdvance(LongConsumer consumer) {
 427             Objects.requireNonNull(consumer);
 428             boolean hasNext = doAdvance();
 429             if (hasNext)
 430                 consumer.accept(buffer.get(nextToConsume));
 431             return hasNext;
 432         }
 433 
 434         @Override
 435         public void forEachRemaining(LongConsumer consumer) {
 436             if (buffer == null && !finished) {
 437                 Objects.requireNonNull(consumer);
 438                 init();
 439 
 440                 ph.wrapAndCopyInto((Sink.OfLong) consumer::accept, spliterator);
 441                 finished = true;
 442             }
 443             else {
 444                 do { } while (tryAdvance(consumer));
 445             }
 446         }
 447     }
 448 
 449     static final class DoubleWrappingSpliterator<P_IN>
 450             extends AbstractWrappingSpliterator<P_IN, Double, SpinedBuffer.OfDouble>
 451             implements Spliterator.OfDouble {
 452 
 453         DoubleWrappingSpliterator(PipelineHelper<Double> ph,
 454                                   Supplier<Spliterator<P_IN>> supplier,
 455                                   boolean parallel) {
 456             super(ph, supplier, parallel);
 457         }
 458 
 459         DoubleWrappingSpliterator(PipelineHelper<Double> ph,
 460                                   Spliterator<P_IN> spliterator,
 461                                   boolean parallel) {
 462             super(ph, spliterator, parallel);
 463         }
 464 
 465         @Override
 466         AbstractWrappingSpliterator<P_IN, Double, SpinedBuffer.OfDouble> wrap(Spliterator<P_IN> s) {
 467             return new DoubleWrappingSpliterator<>(ph, s, isParallel);
 468         }
 469 
 470         @Override
 471         void initPartialTraversalState() {
 472             SpinedBuffer.OfDouble b = new SpinedBuffer.OfDouble();
 473             buffer = b;
 474             bufferSink = ph.wrapSink((Sink.OfDouble) b::accept);
 475         }
 476 
 477         @Override
 478         public Spliterator.OfDouble trySplit() {
 479             return (Spliterator.OfDouble) super.trySplit();
 480         }
 481 
 482         @Override
 483         public boolean tryAdvance(DoubleConsumer consumer) {
 484             Objects.requireNonNull(consumer);
 485             boolean hasNext = doAdvance();
 486             if (hasNext)
 487                 consumer.accept(buffer.get(nextToConsume));
 488             return hasNext;
 489         }
 490 
 491         @Override
 492         public void forEachRemaining(DoubleConsumer consumer) {
 493             if (buffer == null && !finished) {
 494                 Objects.requireNonNull(consumer);
 495                 init();
 496 
 497                 ph.wrapAndCopyInto((Sink.OfDouble) consumer::accept, spliterator);
 498                 finished = true;
 499             }
 500             else {
 501                 do { } while (tryAdvance(consumer));
 502             }
 503         }
 504     }
 505 
 506     /**
 507      * Spliterator implementation that delegates to an underlying spliterator,
 508      * acquiring the spliterator from a {@code Supplier<Spliterator>} on the
 509      * first call to any spliterator method.
 510      * @param <T>
 511      */
 512     static class DelegatingSpliterator<T, T_SPLITR extends Spliterator<T>>
 513             implements Spliterator<T> {
 514         private final Supplier<? extends T_SPLITR> supplier;
 515 
 516         private T_SPLITR s;
 517 
 518         DelegatingSpliterator(Supplier<? extends T_SPLITR> supplier) {
 519             this.supplier = supplier;
 520         }
 521 
 522         T_SPLITR get() {
 523             if (s == null) {
 524                 s = supplier.get();
 525             }
 526             return s;
 527         }
 528 
 529         @Override
 530         @SuppressWarnings("unchecked")
 531         public T_SPLITR trySplit() {
 532             return (T_SPLITR) get().trySplit();
 533         }
 534 
 535         @Override
 536         public boolean tryAdvance(Consumer<? super T> consumer) {
 537             return get().tryAdvance(consumer);
 538         }
 539 
 540         @Override
 541         public void forEachRemaining(Consumer<? super T> consumer) {
 542             get().forEachRemaining(consumer);
 543         }
 544 
 545         @Override
 546         public long estimateSize() {
 547             return get().estimateSize();
 548         }
 549 
 550         @Override
 551         public int characteristics() {
 552             return get().characteristics();
 553         }
 554 
 555         @Override
 556         public Comparator<? super T> getComparator() {
 557             return get().getComparator();
 558         }
 559 
 560         @Override
 561         public long getExactSizeIfKnown() {
 562             return get().getExactSizeIfKnown();
 563         }
 564 
 565         @Override
 566         public String toString() {
 567             return getClass().getName() + "[" + get() + "]";
 568         }
 569 
 570         static class OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
 571             extends DelegatingSpliterator<T, T_SPLITR>
 572             implements Spliterator.OfPrimitive<T, T_CONS, T_SPLITR> {
 573             OfPrimitive(Supplier<? extends T_SPLITR> supplier) {
 574                 super(supplier);
 575             }
 576 
 577             @Override
 578             public boolean tryAdvance(T_CONS consumer) {
 579                 return get().tryAdvance(consumer);
 580             }
 581 
 582             @Override
 583             public void forEachRemaining(T_CONS consumer) {
 584                 get().forEachRemaining(consumer);
 585             }
 586         }
 587 
 588         static final class OfInt
 589                 extends OfPrimitive<Integer, IntConsumer, Spliterator.OfInt>
 590                 implements Spliterator.OfInt {
 591 
 592             OfInt(Supplier<Spliterator.OfInt> supplier) {
 593                 super(supplier);
 594             }
 595         }
 596 
 597         static final class OfLong
 598                 extends OfPrimitive<Long, LongConsumer, Spliterator.OfLong>
 599                 implements Spliterator.OfLong {
 600 
 601             OfLong(Supplier<Spliterator.OfLong> supplier) {
 602                 super(supplier);
 603             }
 604         }
 605 
 606         static final class OfDouble
 607                 extends OfPrimitive<Double, DoubleConsumer, Spliterator.OfDouble>
 608                 implements Spliterator.OfDouble {
 609 
 610             OfDouble(Supplier<Spliterator.OfDouble> supplier) {
 611                 super(supplier);
 612             }
 613         }
 614     }
 615 
 616     /**
 617      * A slice Spliterator from a source Spliterator that reports
 618      * {@code SUBSIZED}.
 619      *
 620      */
 621     abstract static class SliceSpliterator<T, T_SPLITR extends Spliterator<T>> {
 622         // The start index of the slice
 623         final long sliceOrigin;
 624         // One past the last index of the slice
 625         final long sliceFence;
 626 
 627         // The spliterator to slice
 628         T_SPLITR s;
 629         // current (absolute) index, modified on advance/split
 630         long index;
 631         // one past last (absolute) index or sliceFence, which ever is smaller
 632         long fence;
 633 
 634         SliceSpliterator(T_SPLITR s, long sliceOrigin, long sliceFence, long origin, long fence) {
 635             assert s.hasCharacteristics(Spliterator.SUBSIZED);
 636             this.s = s;
 637             this.sliceOrigin = sliceOrigin;
 638             this.sliceFence = sliceFence;
 639             this.index = origin;
 640             this.fence = fence;
 641         }
 642 
 643         protected abstract T_SPLITR makeSpliterator(T_SPLITR s, long sliceOrigin, long sliceFence, long origin, long fence);
 644 
 645         public T_SPLITR trySplit() {
 646             if (sliceOrigin >= fence)
 647                 return null;
 648 
 649             if (index >= fence)
 650                 return null;
 651 
 652             // Keep splitting until the left and right splits intersect with the slice
 653             // thereby ensuring the size estimate decreases.
 654             // This also avoids creating empty spliterators which can result in
 655             // existing and additionally created F/J tasks that perform
 656             // redundant work on no elements.
 657             while (true) {
 658                 @SuppressWarnings("unchecked")
 659                 T_SPLITR leftSplit = (T_SPLITR) s.trySplit();
 660                 if (leftSplit == null)
 661                     return null;
 662 
 663                 long leftSplitFenceUnbounded = index + leftSplit.estimateSize();
 664                 long leftSplitFence = Math.min(leftSplitFenceUnbounded, sliceFence);
 665                 if (sliceOrigin >= leftSplitFence) {
 666                     // The left split does not intersect with, and is to the left of, the slice
 667                     // The right split does intersect
 668                     // Discard the left split and split further with the right split
 669                     index = leftSplitFence;
 670                 }
 671                 else if (leftSplitFence >= sliceFence) {
 672                     // The right split does not intersect with, and is to the right of, the slice
 673                     // The left split does intersect
 674                     // Discard the right split and split further with the left split
 675                     s = leftSplit;
 676                     fence = leftSplitFence;
 677                 }
 678                 else if (index >= sliceOrigin && leftSplitFenceUnbounded <= sliceFence) {
 679                     // The left split is contained within the slice, return the underlying left split
 680                     // Right split is contained within or intersects with the slice
 681                     index = leftSplitFence;
 682                     return leftSplit;
 683                 } else {
 684                     // The left split intersects with the slice
 685                     // Right split is contained within or intersects with the slice
 686                     return makeSpliterator(leftSplit, sliceOrigin, sliceFence, index, index = leftSplitFence);
 687                 }
 688             }
 689         }
 690 
 691         public long estimateSize() {
 692             return (sliceOrigin < fence)
 693                    ? fence - Math.max(sliceOrigin, index) : 0;
 694         }
 695 
 696         public int characteristics() {
 697             return s.characteristics();
 698         }
 699 
 700         static final class OfRef<T>
 701                 extends SliceSpliterator<T, Spliterator<T>>
 702                 implements Spliterator<T> {
 703 
 704             OfRef(Spliterator<T> s, long sliceOrigin, long sliceFence) {
 705                 this(s, sliceOrigin, sliceFence, 0, Math.min(s.estimateSize(), sliceFence));
 706             }
 707 
 708             private OfRef(Spliterator<T> s,
 709                           long sliceOrigin, long sliceFence, long origin, long fence) {
 710                 super(s, sliceOrigin, sliceFence, origin, fence);
 711             }
 712 
 713             @Override
 714             protected Spliterator<T> makeSpliterator(Spliterator<T> s,
 715                                                      long sliceOrigin, long sliceFence,
 716                                                      long origin, long fence) {
 717                 return new OfRef<>(s, sliceOrigin, sliceFence, origin, fence);
 718             }
 719 
 720             @Override
 721             public boolean tryAdvance(Consumer<? super T> action) {
 722                 Objects.requireNonNull(action);
 723 
 724                 if (sliceOrigin >= fence)
 725                     return false;
 726 
 727                 while (sliceOrigin > index) {
 728                     s.tryAdvance(e -> {});
 729                     index++;
 730                 }
 731 
 732                 if (index >= fence)
 733                     return false;
 734 
 735                 index++;
 736                 return s.tryAdvance(action);
 737             }
 738 
 739             @Override
 740             public void forEachRemaining(Consumer<? super T> action) {
 741                 Objects.requireNonNull(action);
 742 
 743                 if (sliceOrigin >= fence)
 744                     return;
 745 
 746                 if (index >= fence)
 747                     return;
 748 
 749                 if (index >= sliceOrigin && (index + s.estimateSize()) <= sliceFence) {
 750                     // The spliterator is contained within the slice
 751                     s.forEachRemaining(action);
 752                     index = fence;
 753                 } else {
 754                     // The spliterator intersects with the slice
 755                     while (sliceOrigin > index) {
 756                         s.tryAdvance(e -> {});
 757                         index++;
 758                     }
 759                     // Traverse elements up to the fence
 760                     for (;index < fence; index++) {
 761                         s.tryAdvance(action);
 762                     }
 763                 }
 764             }
 765         }
 766 
 767         abstract static class OfPrimitive<T,
 768                 T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>,
 769                 T_CONS>
 770                 extends SliceSpliterator<T, T_SPLITR>
 771                 implements Spliterator.OfPrimitive<T, T_CONS, T_SPLITR> {
 772 
 773             OfPrimitive(T_SPLITR s, long sliceOrigin, long sliceFence) {
 774                 this(s, sliceOrigin, sliceFence, 0, Math.min(s.estimateSize(), sliceFence));
 775             }
 776 
 777             private OfPrimitive(T_SPLITR s,
 778                                 long sliceOrigin, long sliceFence, long origin, long fence) {
 779                 super(s, sliceOrigin, sliceFence, origin, fence);
 780             }
 781 
 782             @Override
 783             public boolean tryAdvance(T_CONS action) {
 784                 Objects.requireNonNull(action);
 785 
 786                 if (sliceOrigin >= fence)
 787                     return false;
 788 
 789                 while (sliceOrigin > index) {
 790                     s.tryAdvance(emptyConsumer());
 791                     index++;
 792                 }
 793 
 794                 if (index >= fence)
 795                     return false;
 796 
 797                 index++;
 798                 return s.tryAdvance(action);
 799             }
 800 
 801             @Override
 802             public void forEachRemaining(T_CONS action) {
 803                 Objects.requireNonNull(action);
 804 
 805                 if (sliceOrigin >= fence)
 806                     return;
 807 
 808                 if (index >= fence)
 809                     return;
 810 
 811                 if (index >= sliceOrigin && (index + s.estimateSize()) <= sliceFence) {
 812                     // The spliterator is contained within the slice
 813                     s.forEachRemaining(action);
 814                     index = fence;
 815                 } else {
 816                     // The spliterator intersects with the slice
 817                     while (sliceOrigin > index) {
 818                         s.tryAdvance(emptyConsumer());
 819                         index++;
 820                     }
 821                     // Traverse elements up to the fence
 822                     for (;index < fence; index++) {
 823                         s.tryAdvance(action);
 824                     }
 825                 }
 826             }
 827 
 828             protected abstract T_CONS emptyConsumer();
 829         }
 830 
 831         static final class OfInt extends OfPrimitive<Integer, Spliterator.OfInt, IntConsumer>
 832                 implements Spliterator.OfInt {
 833             OfInt(Spliterator.OfInt s, long sliceOrigin, long sliceFence) {
 834                 super(s, sliceOrigin, sliceFence);
 835             }
 836 
 837             OfInt(Spliterator.OfInt s,
 838                   long sliceOrigin, long sliceFence, long origin, long fence) {
 839                 super(s, sliceOrigin, sliceFence, origin, fence);
 840             }
 841 
 842             @Override
 843             protected Spliterator.OfInt makeSpliterator(Spliterator.OfInt s,
 844                                                         long sliceOrigin, long sliceFence,
 845                                                         long origin, long fence) {
 846                 return new SliceSpliterator.OfInt(s, sliceOrigin, sliceFence, origin, fence);
 847             }
 848 
 849             @Override
 850             protected IntConsumer emptyConsumer() {
 851                 return e -> {};
 852             }
 853         }
 854 
 855         static final class OfLong extends OfPrimitive<Long, Spliterator.OfLong, LongConsumer>
 856                 implements Spliterator.OfLong {
 857             OfLong(Spliterator.OfLong s, long sliceOrigin, long sliceFence) {
 858                 super(s, sliceOrigin, sliceFence);
 859             }
 860 
 861             OfLong(Spliterator.OfLong s,
 862                    long sliceOrigin, long sliceFence, long origin, long fence) {
 863                 super(s, sliceOrigin, sliceFence, origin, fence);
 864             }
 865 
 866             @Override
 867             protected Spliterator.OfLong makeSpliterator(Spliterator.OfLong s,
 868                                                          long sliceOrigin, long sliceFence,
 869                                                          long origin, long fence) {
 870                 return new SliceSpliterator.OfLong(s, sliceOrigin, sliceFence, origin, fence);
 871             }
 872 
 873             @Override
 874             protected LongConsumer emptyConsumer() {
 875                 return e -> {};
 876             }
 877         }
 878 
 879         static final class OfDouble extends OfPrimitive<Double, Spliterator.OfDouble, DoubleConsumer>
 880                 implements Spliterator.OfDouble {
 881             OfDouble(Spliterator.OfDouble s, long sliceOrigin, long sliceFence) {
 882                 super(s, sliceOrigin, sliceFence);
 883             }
 884 
 885             OfDouble(Spliterator.OfDouble s,
 886                      long sliceOrigin, long sliceFence, long origin, long fence) {
 887                 super(s, sliceOrigin, sliceFence, origin, fence);
 888             }
 889 
 890             @Override
 891             protected Spliterator.OfDouble makeSpliterator(Spliterator.OfDouble s,
 892                                                            long sliceOrigin, long sliceFence,
 893                                                            long origin, long fence) {
 894                 return new SliceSpliterator.OfDouble(s, sliceOrigin, sliceFence, origin, fence);
 895             }
 896 
 897             @Override
 898             protected DoubleConsumer emptyConsumer() {
 899                 return e -> {};
 900             }
 901         }
 902     }
 903 
 904     /**
 905      * A slice Spliterator that does not preserve order, if any, of a source
 906      * Spliterator.
 907      *
 908      * Note: The source spliterator may report {@code ORDERED} since that
 909      * spliterator be the result of a previous pipeline stage that was
 910      * collected to a {@code Node}. It is the order of the pipeline stage
 911      * that governs whether the this slice spliterator is to be used or not.
 912      */
 913     abstract static class UnorderedSliceSpliterator<T, T_SPLITR extends Spliterator<T>> {
 914         static final int CHUNK_SIZE = 1 << 7;
 915 
 916         // The spliterator to slice
 917         protected final T_SPLITR s;
 918         protected final boolean unlimited;
 919         private final long skipThreshold;
 920         private final AtomicLong permits;
 921 
 922         UnorderedSliceSpliterator(T_SPLITR s, long skip, long limit) {
 923             this.s = s;
 924             this.unlimited = limit < 0;
 925             this.skipThreshold = limit >= 0 ? limit : 0;
 926             this.permits = new AtomicLong(limit >= 0 ? skip + limit : skip);
 927         }
 928 
 929         UnorderedSliceSpliterator(T_SPLITR s,
 930                                   UnorderedSliceSpliterator<T, T_SPLITR> parent) {
 931             this.s = s;
 932             this.unlimited = parent.unlimited;
 933             this.permits = parent.permits;
 934             this.skipThreshold = parent.skipThreshold;
 935         }
 936 
 937         /**
 938          * Acquire permission to skip or process elements.  The caller must
 939          * first acquire the elements, then consult this method for guidance
 940          * as to what to do with the data.
 941          *
 942          * <p>We use an {@code AtomicLong} to atomically maintain a counter,
 943          * which is initialized as skip+limit if we are limiting, or skip only
 944          * if we are not limiting.  The user should consult the method
 945          * {@code checkPermits()} before acquiring data elements.
 946          *
 947          * @param numElements the number of elements the caller has in hand
 948          * @return the number of elements that should be processed; any
 949          * remaining elements should be discarded.
 950          */
 951         protected final long acquirePermits(long numElements) {
 952             long remainingPermits;
 953             long grabbing;
 954             // permits never increase, and don't decrease below zero
 955             assert numElements > 0;
 956             do {
 957                 remainingPermits = permits.get();
 958                 if (remainingPermits == 0)
 959                     return unlimited ? numElements : 0;
 960                 grabbing = Math.min(remainingPermits, numElements);
 961             } while (grabbing > 0 &&
 962                      !permits.compareAndSet(remainingPermits, remainingPermits - grabbing));
 963 
 964             if (unlimited)
 965                 return Math.max(numElements - grabbing, 0);
 966             else if (remainingPermits > skipThreshold)
 967                 return Math.max(grabbing - (remainingPermits - skipThreshold), 0);
 968             else
 969                 return grabbing;
 970         }
 971 
 972         enum PermitStatus { NO_MORE, MAYBE_MORE, UNLIMITED }
 973 
 974         /** Call to check if permits might be available before acquiring data */
 975         protected final PermitStatus permitStatus() {
 976             if (permits.get() > 0)
 977                 return PermitStatus.MAYBE_MORE;
 978             else
 979                 return unlimited ?  PermitStatus.UNLIMITED : PermitStatus.NO_MORE;
 980         }
 981 
 982         public final T_SPLITR trySplit() {
 983             // Stop splitting when there are no more limit permits
 984             if (permits.get() == 0)
 985                 return null;
 986             @SuppressWarnings("unchecked")
 987             T_SPLITR split = (T_SPLITR) s.trySplit();
 988             return split == null ? null : makeSpliterator(split);
 989         }
 990 
 991         protected abstract T_SPLITR makeSpliterator(T_SPLITR s);
 992 
 993         public final long estimateSize() {
 994             return s.estimateSize();
 995         }
 996 
 997         public final int characteristics() {
 998             return s.characteristics() &
 999                    ~(Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED);
1000         }
1001 
1002         static final class OfRef<T> extends UnorderedSliceSpliterator<T, Spliterator<T>>
1003                 implements Spliterator<T>, Consumer<T> {
1004             T tmpSlot;
1005 
1006             OfRef(Spliterator<T> s, long skip, long limit) {
1007                 super(s, skip, limit);
1008             }
1009 
1010             OfRef(Spliterator<T> s, OfRef<T> parent) {
1011                 super(s, parent);
1012             }
1013 
1014             @Override
1015             public final void accept(T t) {
1016                 tmpSlot = t;
1017             }
1018 
1019             @Override
1020             public boolean tryAdvance(Consumer<? super T> action) {
1021                 Objects.requireNonNull(action);
1022 
1023                 while (permitStatus() != PermitStatus.NO_MORE) {
1024                     if (!s.tryAdvance(this))
1025                         return false;
1026                     else if (acquirePermits(1) == 1) {
1027                         action.accept(tmpSlot);
1028                         tmpSlot = null;
1029                         return true;
1030                     }
1031                 }
1032                 return false;
1033             }
1034 
1035             @Override
1036             public void forEachRemaining(Consumer<? super T> action) {
1037                 Objects.requireNonNull(action);
1038 
1039                 ArrayBuffer.OfRef<T> sb = null;
1040                 PermitStatus permitStatus;
1041                 while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) {
1042                     if (permitStatus == PermitStatus.MAYBE_MORE) {
1043                         // Optimistically traverse elements up to a threshold of CHUNK_SIZE
1044                         if (sb == null)
1045                             sb = new ArrayBuffer.OfRef<>(CHUNK_SIZE);
1046                         else
1047                             sb.reset();
1048                         long permitsRequested = 0;
1049                         do { } while (s.tryAdvance(sb) && ++permitsRequested < CHUNK_SIZE);
1050                         if (permitsRequested == 0)
1051                             return;
1052                         sb.forEach(action, acquirePermits(permitsRequested));
1053                     }
1054                     else {
1055                         // Must be UNLIMITED; let 'er rip
1056                         s.forEachRemaining(action);
1057                         return;
1058                     }
1059                 }
1060             }
1061 
1062             @Override
1063             protected Spliterator<T> makeSpliterator(Spliterator<T> s) {
1064                 return new UnorderedSliceSpliterator.OfRef<>(s, this);
1065             }
1066         }
1067 
1068         /**
1069          * Concrete sub-types must also be an instance of type {@code T_CONS}.
1070          *
1071          * @param <T_BUFF> the type of the spined buffer. Must also be a type of
1072          *        {@code T_CONS}.
1073          */
1074         abstract static class OfPrimitive<
1075                 T,
1076                 T_CONS,
1077                 T_BUFF extends ArrayBuffer.OfPrimitive<T_CONS>,
1078                 T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
1079                 extends UnorderedSliceSpliterator<T, T_SPLITR>
1080                 implements Spliterator.OfPrimitive<T, T_CONS, T_SPLITR> {
1081             OfPrimitive(T_SPLITR s, long skip, long limit) {
1082                 super(s, skip, limit);
1083             }
1084 
1085             OfPrimitive(T_SPLITR s, UnorderedSliceSpliterator.OfPrimitive<T, T_CONS, T_BUFF, T_SPLITR> parent) {
1086                 super(s, parent);
1087             }
1088 
1089             @Override
1090             public boolean tryAdvance(T_CONS action) {
1091                 Objects.requireNonNull(action);
1092                 @SuppressWarnings("unchecked")
1093                 T_CONS consumer = (T_CONS) this;
1094 
1095                 while (permitStatus() != PermitStatus.NO_MORE) {
1096                     if (!s.tryAdvance(consumer))
1097                         return false;
1098                     else if (acquirePermits(1) == 1) {
1099                         acceptConsumed(action);
1100                         return true;
1101                     }
1102                 }
1103                 return false;
1104             }
1105 
1106             protected abstract void acceptConsumed(T_CONS action);
1107 
1108             @Override
1109             public void forEachRemaining(T_CONS action) {
1110                 Objects.requireNonNull(action);
1111 
1112                 T_BUFF sb = null;
1113                 PermitStatus permitStatus;
1114                 while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) {
1115                     if (permitStatus == PermitStatus.MAYBE_MORE) {
1116                         // Optimistically traverse elements up to a threshold of CHUNK_SIZE
1117                         if (sb == null)
1118                             sb = bufferCreate(CHUNK_SIZE);
1119                         else
1120                             sb.reset();
1121                         @SuppressWarnings("unchecked")
1122                         T_CONS sbc = (T_CONS) sb;
1123                         long permitsRequested = 0;
1124                         do { } while (s.tryAdvance(sbc) && ++permitsRequested < CHUNK_SIZE);
1125                         if (permitsRequested == 0)
1126                             return;
1127                         sb.forEach(action, acquirePermits(permitsRequested));
1128                     }
1129                     else {
1130                         // Must be UNLIMITED; let 'er rip
1131                         s.forEachRemaining(action);
1132                         return;
1133                     }
1134                 }
1135             }
1136 
1137             protected abstract T_BUFF bufferCreate(int initialCapacity);
1138         }
1139 
1140         static final class OfInt
1141                 extends OfPrimitive<Integer, IntConsumer, ArrayBuffer.OfInt, Spliterator.OfInt>
1142                 implements Spliterator.OfInt, IntConsumer {
1143 
1144             int tmpValue;
1145 
1146             OfInt(Spliterator.OfInt s, long skip, long limit) {
1147                 super(s, skip, limit);
1148             }
1149 
1150             OfInt(Spliterator.OfInt s, UnorderedSliceSpliterator.OfInt parent) {
1151                 super(s, parent);
1152             }
1153 
1154             @Override
1155             public void accept(int value) {
1156                 tmpValue = value;
1157             }
1158 
1159             @Override
1160             protected void acceptConsumed(IntConsumer action) {
1161                 action.accept(tmpValue);
1162             }
1163 
1164             @Override
1165             protected ArrayBuffer.OfInt bufferCreate(int initialCapacity) {
1166                 return new ArrayBuffer.OfInt(initialCapacity);
1167             }
1168 
1169             @Override
1170             protected Spliterator.OfInt makeSpliterator(Spliterator.OfInt s) {
1171                 return new UnorderedSliceSpliterator.OfInt(s, this);
1172             }
1173         }
1174 
1175         static final class OfLong
1176                 extends OfPrimitive<Long, LongConsumer, ArrayBuffer.OfLong, Spliterator.OfLong>
1177                 implements Spliterator.OfLong, LongConsumer {
1178 
1179             long tmpValue;
1180 
1181             OfLong(Spliterator.OfLong s, long skip, long limit) {
1182                 super(s, skip, limit);
1183             }
1184 
1185             OfLong(Spliterator.OfLong s, UnorderedSliceSpliterator.OfLong parent) {
1186                 super(s, parent);
1187             }
1188 
1189             @Override
1190             public void accept(long value) {
1191                 tmpValue = value;
1192             }
1193 
1194             @Override
1195             protected void acceptConsumed(LongConsumer action) {
1196                 action.accept(tmpValue);
1197             }
1198 
1199             @Override
1200             protected ArrayBuffer.OfLong bufferCreate(int initialCapacity) {
1201                 return new ArrayBuffer.OfLong(initialCapacity);
1202             }
1203 
1204             @Override
1205             protected Spliterator.OfLong makeSpliterator(Spliterator.OfLong s) {
1206                 return new UnorderedSliceSpliterator.OfLong(s, this);
1207             }
1208         }
1209 
1210         static final class OfDouble
1211                 extends OfPrimitive<Double, DoubleConsumer, ArrayBuffer.OfDouble, Spliterator.OfDouble>
1212                 implements Spliterator.OfDouble, DoubleConsumer {
1213 
1214             double tmpValue;
1215 
1216             OfDouble(Spliterator.OfDouble s, long skip, long limit) {
1217                 super(s, skip, limit);
1218             }
1219 
1220             OfDouble(Spliterator.OfDouble s, UnorderedSliceSpliterator.OfDouble parent) {
1221                 super(s, parent);
1222             }
1223 
1224             @Override
1225             public void accept(double value) {
1226                 tmpValue = value;
1227             }
1228 
1229             @Override
1230             protected void acceptConsumed(DoubleConsumer action) {
1231                 action.accept(tmpValue);
1232             }
1233 
1234             @Override
1235             protected ArrayBuffer.OfDouble bufferCreate(int initialCapacity) {
1236                 return new ArrayBuffer.OfDouble(initialCapacity);
1237             }
1238 
1239             @Override
1240             protected Spliterator.OfDouble makeSpliterator(Spliterator.OfDouble s) {
1241                 return new UnorderedSliceSpliterator.OfDouble(s, this);
1242             }
1243         }
1244     }
1245 
1246     /**
1247      * A wrapping spliterator that only reports distinct elements of the
1248      * underlying spliterator. Does not preserve size and encounter order.
1249      */
1250     static final class DistinctSpliterator<T> implements Spliterator<T>, Consumer<T> {
1251 
1252         // The value to represent null in the ConcurrentHashMap
1253         private static final Object NULL_VALUE = new Object();
1254 
1255         // The underlying spliterator
1256         private final Spliterator<T> s;
1257 
1258         // ConcurrentHashMap holding distinct elements as keys
1259         private final ConcurrentHashMap<T, Boolean> seen;
1260 
1261         // Temporary element, only used with tryAdvance
1262         private T tmpSlot;
1263 
1264         DistinctSpliterator(Spliterator<T> s) {
1265             this(s, new ConcurrentHashMap<>());
1266         }
1267 
1268         private DistinctSpliterator(Spliterator<T> s, ConcurrentHashMap<T, Boolean> seen) {
1269             this.s = s;
1270             this.seen = seen;
1271         }
1272 
1273         @Override
1274         public void accept(T t) {
1275             this.tmpSlot = t;
1276         }
1277 
1278         @SuppressWarnings("unchecked")
1279         private T mapNull(T t) {
1280             return t != null ? t : (T) NULL_VALUE;
1281         }
1282 
1283         @Override
1284         public boolean tryAdvance(Consumer<? super T> action) {
1285             while (s.tryAdvance(this)) {
1286                 if (seen.putIfAbsent(mapNull(tmpSlot), Boolean.TRUE) == null) {
1287                     action.accept(tmpSlot);
1288                     tmpSlot = null;
1289                     return true;
1290                 }
1291             }
1292             return false;
1293         }
1294 
1295         @Override
1296         public void forEachRemaining(Consumer<? super T> action) {
1297             s.forEachRemaining(t -> {
1298                 if (seen.putIfAbsent(mapNull(t), Boolean.TRUE) == null) {
1299                     action.accept(t);
1300                 }
1301             });
1302         }
1303 
1304         @Override
1305         public Spliterator<T> trySplit() {
1306             Spliterator<T> split = s.trySplit();
1307             return (split != null) ? new DistinctSpliterator<>(split, seen) : null;
1308         }
1309 
1310         @Override
1311         public long estimateSize() {
1312             return s.estimateSize();
1313         }
1314 
1315         @Override
1316         public int characteristics() {
1317             return (s.characteristics() & ~(Spliterator.SIZED | Spliterator.SUBSIZED |
1318                                             Spliterator.SORTED | Spliterator.ORDERED))
1319                    | Spliterator.DISTINCT;
1320         }
1321 
1322         @Override
1323         public Comparator<? super T> getComparator() {
1324             return s.getComparator();
1325         }
1326     }
1327 
1328     /**
1329      * A Spliterator that infinitely supplies elements in no particular order.
1330      *
1331      * <p>Splitting divides the estimated size in two and stops when the
1332      * estimate size is 0.
1333      *
1334      * <p>The {@code forEachRemaining} method if invoked will never terminate.
1335      * The {@code tryAdvance} method always returns true.
1336      *
1337      */
1338     abstract static class InfiniteSupplyingSpliterator<T> implements Spliterator<T> {
1339         long estimate;
1340 
1341         protected InfiniteSupplyingSpliterator(long estimate) {
1342             this.estimate = estimate;
1343         }
1344 
1345         @Override
1346         public long estimateSize() {
1347             return estimate;
1348         }
1349 
1350         @Override
1351         public int characteristics() {
1352             return IMMUTABLE;
1353         }
1354 
1355         static final class OfRef<T> extends InfiniteSupplyingSpliterator<T> {
1356             final Supplier<T> s;
1357 
1358             OfRef(long size, Supplier<T> s) {
1359                 super(size);
1360                 this.s = s;
1361             }
1362 
1363             @Override
1364             public boolean tryAdvance(Consumer<? super T> action) {
1365                 Objects.requireNonNull(action);
1366 
1367                 action.accept(s.get());
1368                 return true;
1369             }
1370 
1371             @Override
1372             public Spliterator<T> trySplit() {
1373                 if (estimate == 0)
1374                     return null;
1375                 return new InfiniteSupplyingSpliterator.OfRef<>(estimate >>>= 1, s);
1376             }
1377         }
1378 
1379         static final class OfInt extends InfiniteSupplyingSpliterator<Integer>
1380                 implements Spliterator.OfInt {
1381             final IntSupplier s;
1382 
1383             OfInt(long size, IntSupplier s) {
1384                 super(size);
1385                 this.s = s;
1386             }
1387 
1388             @Override
1389             public boolean tryAdvance(IntConsumer action) {
1390                 Objects.requireNonNull(action);
1391 
1392                 action.accept(s.getAsInt());
1393                 return true;
1394             }
1395 
1396             @Override
1397             public Spliterator.OfInt trySplit() {
1398                 if (estimate == 0)
1399                     return null;
1400                 return new InfiniteSupplyingSpliterator.OfInt(estimate = estimate >>> 1, s);
1401             }
1402         }
1403 
1404         static final class OfLong extends InfiniteSupplyingSpliterator<Long>
1405                 implements Spliterator.OfLong {
1406             final LongSupplier s;
1407 
1408             OfLong(long size, LongSupplier s) {
1409                 super(size);
1410                 this.s = s;
1411             }
1412 
1413             @Override
1414             public boolean tryAdvance(LongConsumer action) {
1415                 Objects.requireNonNull(action);
1416 
1417                 action.accept(s.getAsLong());
1418                 return true;
1419             }
1420 
1421             @Override
1422             public Spliterator.OfLong trySplit() {
1423                 if (estimate == 0)
1424                     return null;
1425                 return new InfiniteSupplyingSpliterator.OfLong(estimate = estimate >>> 1, s);
1426             }
1427         }
1428 
1429         static final class OfDouble extends InfiniteSupplyingSpliterator<Double>
1430                 implements Spliterator.OfDouble {
1431             final DoubleSupplier s;
1432 
1433             OfDouble(long size, DoubleSupplier s) {
1434                 super(size);
1435                 this.s = s;
1436             }
1437 
1438             @Override
1439             public boolean tryAdvance(DoubleConsumer action) {
1440                 Objects.requireNonNull(action);
1441 
1442                 action.accept(s.getAsDouble());
1443                 return true;
1444             }
1445 
1446             @Override
1447             public Spliterator.OfDouble trySplit() {
1448                 if (estimate == 0)
1449                     return null;
1450                 return new InfiniteSupplyingSpliterator.OfDouble(estimate = estimate >>> 1, s);
1451             }
1452         }
1453     }
1454 
1455     // @@@ Consolidate with Node.Builder
1456     abstract static class ArrayBuffer {
1457         int index;
1458 
1459         void reset() {
1460             index = 0;
1461         }
1462 
1463         static final class OfRef<T> extends ArrayBuffer implements Consumer<T> {
1464             final Object[] array;
1465 
1466             OfRef(int size) {
1467                 this.array = new Object[size];
1468             }
1469 
1470             @Override
1471             public void accept(T t) {
1472                 array[index++] = t;
1473             }
1474 
1475             public void forEach(Consumer<? super T> action, long fence) {
1476                 for (int i = 0; i < fence; i++) {
1477                     @SuppressWarnings("unchecked")
1478                     T t = (T) array[i];
1479                     action.accept(t);
1480                 }
1481             }
1482         }
1483 
1484         abstract static class OfPrimitive<T_CONS> extends ArrayBuffer {
1485             int index;
1486 
1487             @Override
1488             void reset() {
1489                 index = 0;
1490             }
1491 
1492             abstract void forEach(T_CONS action, long fence);
1493         }
1494 
1495         static final class OfInt extends OfPrimitive<IntConsumer>
1496                 implements IntConsumer {
1497             final int[] array;
1498 
1499             OfInt(int size) {
1500                 this.array = new int[size];
1501             }
1502 
1503             @Override
1504             public void accept(int t) {
1505                 array[index++] = t;
1506             }
1507 
1508             @Override
1509             public void forEach(IntConsumer action, long fence) {
1510                 for (int i = 0; i < fence; i++) {
1511                     action.accept(array[i]);
1512                 }
1513             }
1514         }
1515 
1516         static final class OfLong extends OfPrimitive<LongConsumer>
1517                 implements LongConsumer {
1518             final long[] array;
1519 
1520             OfLong(int size) {
1521                 this.array = new long[size];
1522             }
1523 
1524             @Override
1525             public void accept(long t) {
1526                 array[index++] = t;
1527             }
1528 
1529             @Override
1530             public void forEach(LongConsumer action, long fence) {
1531                 for (int i = 0; i < fence; i++) {
1532                     action.accept(array[i]);
1533                 }
1534             }
1535         }
1536 
1537         static final class OfDouble extends OfPrimitive<DoubleConsumer>
1538                 implements DoubleConsumer {
1539             final double[] array;
1540 
1541             OfDouble(int size) {
1542                 this.array = new double[size];
1543             }
1544 
1545             @Override
1546             public void accept(double t) {
1547                 array[index++] = t;
1548             }
1549 
1550             @Override
1551             void forEach(DoubleConsumer action, long fence) {
1552                 for (int i = 0; i < fence; i++) {
1553                     action.accept(array[i]);
1554                 }
1555             }
1556         }
1557     }
1558 }
1559