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