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.function.Consumer; 31 import java.util.function.DoubleConsumer; 32 import java.util.function.IntConsumer; 33 import java.util.function.LongConsumer; 34 35 /** 36 * Utility methods for operating on and creating streams. 37 * 38 * <p>Unless otherwise stated, streams are created as sequential streams. A 39 * sequential stream can be transformed into a parallel stream by calling the 40 * {@code parallel()} method on the created stream. 41 * 42 * @since 1.8 43 */ 44 final class Streams { 45 Streams()46 private Streams() { 47 throw new Error("no instances"); 48 } 49 50 /** 51 * An object instance representing no value, that cannot be an actual 52 * data element of a stream. Used when processing streams that can contain 53 * {@code null} elements to distinguish between a {@code null} value and no 54 * value. 55 */ 56 static final Object NONE = new Object(); 57 58 /** 59 * An {@code int} range spliterator. 60 */ 61 static final class RangeIntSpliterator implements Spliterator.OfInt { 62 // Can never be greater that upTo, this avoids overflow if upper bound 63 // is Integer.MAX_VALUE 64 // All elements are traversed if from == upTo & last == 0 65 private int from; 66 private final int upTo; 67 // 1 if the range is closed and the last element has not been traversed 68 // Otherwise, 0 if the range is open, or is a closed range and all 69 // elements have been traversed 70 private int last; 71 RangeIntSpliterator(int from, int upTo, boolean closed)72 RangeIntSpliterator(int from, int upTo, boolean closed) { 73 this(from, upTo, closed ? 1 : 0); 74 } 75 RangeIntSpliterator(int from, int upTo, int last)76 private RangeIntSpliterator(int from, int upTo, int last) { 77 this.from = from; 78 this.upTo = upTo; 79 this.last = last; 80 } 81 82 @Override tryAdvance(IntConsumer consumer)83 public boolean tryAdvance(IntConsumer consumer) { 84 Objects.requireNonNull(consumer); 85 86 final int i = from; 87 if (i < upTo) { 88 from++; 89 consumer.accept(i); 90 return true; 91 } 92 else if (last > 0) { 93 last = 0; 94 consumer.accept(i); 95 return true; 96 } 97 return false; 98 } 99 100 @Override forEachRemaining(IntConsumer consumer)101 public void forEachRemaining(IntConsumer consumer) { 102 Objects.requireNonNull(consumer); 103 104 int i = from; 105 final int hUpTo = upTo; 106 int hLast = last; 107 from = upTo; 108 last = 0; 109 while (i < hUpTo) { 110 consumer.accept(i++); 111 } 112 if (hLast > 0) { 113 // Last element of closed range 114 consumer.accept(i); 115 } 116 } 117 118 @Override estimateSize()119 public long estimateSize() { 120 // Ensure ranges of size > Integer.MAX_VALUE report the correct size 121 return ((long) upTo) - from + last; 122 } 123 124 @Override characteristics()125 public int characteristics() { 126 return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED | 127 Spliterator.IMMUTABLE | Spliterator.NONNULL | 128 Spliterator.DISTINCT | Spliterator.SORTED; 129 } 130 131 @Override getComparator()132 public Comparator<? super Integer> getComparator() { 133 return null; 134 } 135 136 @Override trySplit()137 public Spliterator.OfInt trySplit() { 138 long size = estimateSize(); 139 return size <= 1 140 ? null 141 // Left split always has a half-open range 142 : new RangeIntSpliterator(from, from = from + splitPoint(size), 0); 143 } 144 145 /** 146 * The spliterator size below which the spliterator will be split 147 * at the mid-point to produce balanced splits. Above this size the 148 * spliterator will be split at a ratio of 149 * 1:(RIGHT_BALANCED_SPLIT_RATIO - 1) 150 * to produce right-balanced splits. 151 * 152 * <p>Such splitting ensures that for very large ranges that the left 153 * side of the range will more likely be processed at a lower-depth 154 * than a balanced tree at the expense of a higher-depth for the right 155 * side of the range. 156 * 157 * <p>This is optimized for cases such as IntStream.ints() that is 158 * implemented as range of 0 to Integer.MAX_VALUE but is likely to be 159 * augmented with a limit operation that limits the number of elements 160 * to a count lower than this threshold. 161 */ 162 private static final int BALANCED_SPLIT_THRESHOLD = 1 << 24; 163 164 /** 165 * The split ratio of the left and right split when the spliterator 166 * size is above BALANCED_SPLIT_THRESHOLD. 167 */ 168 private static final int RIGHT_BALANCED_SPLIT_RATIO = 1 << 3; 169 splitPoint(long size)170 private int splitPoint(long size) { 171 int d = (size < BALANCED_SPLIT_THRESHOLD) ? 2 : RIGHT_BALANCED_SPLIT_RATIO; 172 // Cast to int is safe since: 173 // 2 <= size < 2^32 174 // 2 <= d <= 8 175 return (int) (size / d); 176 } 177 } 178 179 /** 180 * A {@code long} range spliterator. 181 * 182 * This implementation cannot be used for ranges whose size is greater 183 * than Long.MAX_VALUE 184 */ 185 static final class RangeLongSpliterator implements Spliterator.OfLong { 186 // Can never be greater that upTo, this avoids overflow if upper bound 187 // is Long.MAX_VALUE 188 // All elements are traversed if from == upTo & last == 0 189 private long from; 190 private final long upTo; 191 // 1 if the range is closed and the last element has not been traversed 192 // Otherwise, 0 if the range is open, or is a closed range and all 193 // elements have been traversed 194 private int last; 195 RangeLongSpliterator(long from, long upTo, boolean closed)196 RangeLongSpliterator(long from, long upTo, boolean closed) { 197 this(from, upTo, closed ? 1 : 0); 198 } 199 RangeLongSpliterator(long from, long upTo, int last)200 private RangeLongSpliterator(long from, long upTo, int last) { 201 assert upTo - from + last > 0; 202 this.from = from; 203 this.upTo = upTo; 204 this.last = last; 205 } 206 207 @Override tryAdvance(LongConsumer consumer)208 public boolean tryAdvance(LongConsumer consumer) { 209 Objects.requireNonNull(consumer); 210 211 final long i = from; 212 if (i < upTo) { 213 from++; 214 consumer.accept(i); 215 return true; 216 } 217 else if (last > 0) { 218 last = 0; 219 consumer.accept(i); 220 return true; 221 } 222 return false; 223 } 224 225 @Override forEachRemaining(LongConsumer consumer)226 public void forEachRemaining(LongConsumer consumer) { 227 Objects.requireNonNull(consumer); 228 229 long i = from; 230 final long hUpTo = upTo; 231 int hLast = last; 232 from = upTo; 233 last = 0; 234 while (i < hUpTo) { 235 consumer.accept(i++); 236 } 237 if (hLast > 0) { 238 // Last element of closed range 239 consumer.accept(i); 240 } 241 } 242 243 @Override estimateSize()244 public long estimateSize() { 245 return upTo - from + last; 246 } 247 248 @Override characteristics()249 public int characteristics() { 250 return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED | 251 Spliterator.IMMUTABLE | Spliterator.NONNULL | 252 Spliterator.DISTINCT | Spliterator.SORTED; 253 } 254 255 @Override getComparator()256 public Comparator<? super Long> getComparator() { 257 return null; 258 } 259 260 @Override trySplit()261 public Spliterator.OfLong trySplit() { 262 long size = estimateSize(); 263 return size <= 1 264 ? null 265 // Left split always has a half-open range 266 : new RangeLongSpliterator(from, from = from + splitPoint(size), 0); 267 } 268 269 /** 270 * The spliterator size below which the spliterator will be split 271 * at the mid-point to produce balanced splits. Above this size the 272 * spliterator will be split at a ratio of 273 * 1:(RIGHT_BALANCED_SPLIT_RATIO - 1) 274 * to produce right-balanced splits. 275 * 276 * <p>Such splitting ensures that for very large ranges that the left 277 * side of the range will more likely be processed at a lower-depth 278 * than a balanced tree at the expense of a higher-depth for the right 279 * side of the range. 280 * 281 * <p>This is optimized for cases such as LongStream.longs() that is 282 * implemented as range of 0 to Long.MAX_VALUE but is likely to be 283 * augmented with a limit operation that limits the number of elements 284 * to a count lower than this threshold. 285 */ 286 private static final long BALANCED_SPLIT_THRESHOLD = 1 << 24; 287 288 /** 289 * The split ratio of the left and right split when the spliterator 290 * size is above BALANCED_SPLIT_THRESHOLD. 291 */ 292 private static final long RIGHT_BALANCED_SPLIT_RATIO = 1 << 3; 293 splitPoint(long size)294 private long splitPoint(long size) { 295 long d = (size < BALANCED_SPLIT_THRESHOLD) ? 2 : RIGHT_BALANCED_SPLIT_RATIO; 296 // 2 <= size <= Long.MAX_VALUE 297 return size / d; 298 } 299 } 300 301 private static abstract class AbstractStreamBuilderImpl<T, S extends Spliterator<T>> implements Spliterator<T> { 302 // >= 0 when building, < 0 when built 303 // -1 == no elements 304 // -2 == one element, held by first 305 // -3 == two or more elements, held by buffer 306 int count; 307 308 // Spliterator implementation for 0 or 1 element 309 // count == -1 for no elements 310 // count == -2 for one element held by first 311 312 @Override trySplit()313 public S trySplit() { 314 return null; 315 } 316 317 @Override estimateSize()318 public long estimateSize() { 319 return -count - 1; 320 } 321 322 @Override characteristics()323 public int characteristics() { 324 return Spliterator.SIZED | Spliterator.SUBSIZED | 325 Spliterator.ORDERED | Spliterator.IMMUTABLE; 326 } 327 } 328 329 static final class StreamBuilderImpl<T> 330 extends AbstractStreamBuilderImpl<T, Spliterator<T>> 331 implements Stream.Builder<T> { 332 // The first element in the stream 333 // valid if count == 1 334 T first; 335 336 // The first and subsequent elements in the stream 337 // non-null if count == 2 338 SpinedBuffer<T> buffer; 339 340 /** 341 * Constructor for building a stream of 0 or more elements. 342 */ StreamBuilderImpl()343 StreamBuilderImpl() { } 344 345 /** 346 * Constructor for a singleton stream. 347 * 348 * @param t the single element 349 */ StreamBuilderImpl(T t)350 StreamBuilderImpl(T t) { 351 first = t; 352 count = -2; 353 } 354 355 // StreamBuilder implementation 356 357 @Override accept(T t)358 public void accept(T t) { 359 if (count == 0) { 360 first = t; 361 count++; 362 } 363 else if (count > 0) { 364 if (buffer == null) { 365 buffer = new SpinedBuffer<>(); 366 buffer.accept(first); 367 count++; 368 } 369 370 buffer.accept(t); 371 } 372 else { 373 throw new IllegalStateException(); 374 } 375 } 376 add(T t)377 public Stream.Builder<T> add(T t) { 378 accept(t); 379 return this; 380 } 381 382 @Override build()383 public Stream<T> build() { 384 int c = count; 385 if (c >= 0) { 386 // Switch count to negative value signalling the builder is built 387 count = -count - 1; 388 // Use this spliterator if 0 or 1 elements, otherwise use 389 // the spliterator of the spined buffer 390 return (c < 2) ? StreamSupport.stream(this, false) : StreamSupport.stream(buffer.spliterator(), false); 391 } 392 393 throw new IllegalStateException(); 394 } 395 396 // Spliterator implementation for 0 or 1 element 397 // count == -1 for no elements 398 // count == -2 for one element held by first 399 400 @Override tryAdvance(Consumer<? super T> action)401 public boolean tryAdvance(Consumer<? super T> action) { 402 Objects.requireNonNull(action); 403 404 if (count == -2) { 405 action.accept(first); 406 count = -1; 407 return true; 408 } 409 else { 410 return false; 411 } 412 } 413 414 @Override forEachRemaining(Consumer<? super T> action)415 public void forEachRemaining(Consumer<? super T> action) { 416 Objects.requireNonNull(action); 417 418 if (count == -2) { 419 action.accept(first); 420 count = -1; 421 } 422 } 423 } 424 425 static final class IntStreamBuilderImpl 426 extends AbstractStreamBuilderImpl<Integer, Spliterator.OfInt> 427 implements IntStream.Builder, Spliterator.OfInt { 428 // The first element in the stream 429 // valid if count == 1 430 int first; 431 432 // The first and subsequent elements in the stream 433 // non-null if count == 2 434 SpinedBuffer.OfInt buffer; 435 436 /** 437 * Constructor for building a stream of 0 or more elements. 438 */ IntStreamBuilderImpl()439 IntStreamBuilderImpl() { } 440 441 /** 442 * Constructor for a singleton stream. 443 * 444 * @param t the single element 445 */ IntStreamBuilderImpl(int t)446 IntStreamBuilderImpl(int t) { 447 first = t; 448 count = -2; 449 } 450 451 // StreamBuilder implementation 452 453 @Override accept(int t)454 public void accept(int t) { 455 if (count == 0) { 456 first = t; 457 count++; 458 } 459 else if (count > 0) { 460 if (buffer == null) { 461 buffer = new SpinedBuffer.OfInt(); 462 buffer.accept(first); 463 count++; 464 } 465 466 buffer.accept(t); 467 } 468 else { 469 throw new IllegalStateException(); 470 } 471 } 472 473 @Override build()474 public IntStream build() { 475 int c = count; 476 if (c >= 0) { 477 // Switch count to negative value signalling the builder is built 478 count = -count - 1; 479 // Use this spliterator if 0 or 1 elements, otherwise use 480 // the spliterator of the spined buffer 481 return (c < 2) ? StreamSupport.intStream(this, false) : StreamSupport.intStream(buffer.spliterator(), false); 482 } 483 484 throw new IllegalStateException(); 485 } 486 487 // Spliterator implementation for 0 or 1 element 488 // count == -1 for no elements 489 // count == -2 for one element held by first 490 491 @Override tryAdvance(IntConsumer action)492 public boolean tryAdvance(IntConsumer action) { 493 Objects.requireNonNull(action); 494 495 if (count == -2) { 496 action.accept(first); 497 count = -1; 498 return true; 499 } 500 else { 501 return false; 502 } 503 } 504 505 @Override forEachRemaining(IntConsumer action)506 public void forEachRemaining(IntConsumer action) { 507 Objects.requireNonNull(action); 508 509 if (count == -2) { 510 action.accept(first); 511 count = -1; 512 } 513 } 514 } 515 516 static final class LongStreamBuilderImpl 517 extends AbstractStreamBuilderImpl<Long, Spliterator.OfLong> 518 implements LongStream.Builder, Spliterator.OfLong { 519 // The first element in the stream 520 // valid if count == 1 521 long first; 522 523 // The first and subsequent elements in the stream 524 // non-null if count == 2 525 SpinedBuffer.OfLong buffer; 526 527 /** 528 * Constructor for building a stream of 0 or more elements. 529 */ LongStreamBuilderImpl()530 LongStreamBuilderImpl() { } 531 532 /** 533 * Constructor for a singleton stream. 534 * 535 * @param t the single element 536 */ LongStreamBuilderImpl(long t)537 LongStreamBuilderImpl(long t) { 538 first = t; 539 count = -2; 540 } 541 542 // StreamBuilder implementation 543 544 @Override accept(long t)545 public void accept(long t) { 546 if (count == 0) { 547 first = t; 548 count++; 549 } 550 else if (count > 0) { 551 if (buffer == null) { 552 buffer = new SpinedBuffer.OfLong(); 553 buffer.accept(first); 554 count++; 555 } 556 557 buffer.accept(t); 558 } 559 else { 560 throw new IllegalStateException(); 561 } 562 } 563 564 @Override build()565 public LongStream build() { 566 int c = count; 567 if (c >= 0) { 568 // Switch count to negative value signalling the builder is built 569 count = -count - 1; 570 // Use this spliterator if 0 or 1 elements, otherwise use 571 // the spliterator of the spined buffer 572 return (c < 2) ? StreamSupport.longStream(this, false) : StreamSupport.longStream(buffer.spliterator(), false); 573 } 574 575 throw new IllegalStateException(); 576 } 577 578 // Spliterator implementation for 0 or 1 element 579 // count == -1 for no elements 580 // count == -2 for one element held by first 581 582 @Override tryAdvance(LongConsumer action)583 public boolean tryAdvance(LongConsumer action) { 584 Objects.requireNonNull(action); 585 586 if (count == -2) { 587 action.accept(first); 588 count = -1; 589 return true; 590 } 591 else { 592 return false; 593 } 594 } 595 596 @Override forEachRemaining(LongConsumer action)597 public void forEachRemaining(LongConsumer action) { 598 Objects.requireNonNull(action); 599 600 if (count == -2) { 601 action.accept(first); 602 count = -1; 603 } 604 } 605 } 606 607 static final class DoubleStreamBuilderImpl 608 extends AbstractStreamBuilderImpl<Double, Spliterator.OfDouble> 609 implements DoubleStream.Builder, Spliterator.OfDouble { 610 // The first element in the stream 611 // valid if count == 1 612 double first; 613 614 // The first and subsequent elements in the stream 615 // non-null if count == 2 616 SpinedBuffer.OfDouble buffer; 617 618 /** 619 * Constructor for building a stream of 0 or more elements. 620 */ DoubleStreamBuilderImpl()621 DoubleStreamBuilderImpl() { } 622 623 /** 624 * Constructor for a singleton stream. 625 * 626 * @param t the single element 627 */ DoubleStreamBuilderImpl(double t)628 DoubleStreamBuilderImpl(double t) { 629 first = t; 630 count = -2; 631 } 632 633 // StreamBuilder implementation 634 635 @Override accept(double t)636 public void accept(double t) { 637 if (count == 0) { 638 first = t; 639 count++; 640 } 641 else if (count > 0) { 642 if (buffer == null) { 643 buffer = new SpinedBuffer.OfDouble(); 644 buffer.accept(first); 645 count++; 646 } 647 648 buffer.accept(t); 649 } 650 else { 651 throw new IllegalStateException(); 652 } 653 } 654 655 @Override build()656 public DoubleStream build() { 657 int c = count; 658 if (c >= 0) { 659 // Switch count to negative value signalling the builder is built 660 count = -count - 1; 661 // Use this spliterator if 0 or 1 elements, otherwise use 662 // the spliterator of the spined buffer 663 return (c < 2) ? StreamSupport.doubleStream(this, false) : StreamSupport.doubleStream(buffer.spliterator(), false); 664 } 665 666 throw new IllegalStateException(); 667 } 668 669 // Spliterator implementation for 0 or 1 element 670 // count == -1 for no elements 671 // count == -2 for one element held by first 672 673 @Override tryAdvance(DoubleConsumer action)674 public boolean tryAdvance(DoubleConsumer action) { 675 Objects.requireNonNull(action); 676 677 if (count == -2) { 678 action.accept(first); 679 count = -1; 680 return true; 681 } 682 else { 683 return false; 684 } 685 } 686 687 @Override forEachRemaining(DoubleConsumer action)688 public void forEachRemaining(DoubleConsumer action) { 689 Objects.requireNonNull(action); 690 691 if (count == -2) { 692 action.accept(first); 693 count = -1; 694 } 695 } 696 } 697 698 abstract static class ConcatSpliterator<T, T_SPLITR extends Spliterator<T>> 699 implements Spliterator<T> { 700 protected final T_SPLITR aSpliterator; 701 protected final T_SPLITR bSpliterator; 702 // True when no split has occurred, otherwise false 703 boolean beforeSplit; 704 // Never read after splitting 705 final boolean unsized; 706 ConcatSpliterator(T_SPLITR aSpliterator, T_SPLITR bSpliterator)707 public ConcatSpliterator(T_SPLITR aSpliterator, T_SPLITR bSpliterator) { 708 this.aSpliterator = aSpliterator; 709 this.bSpliterator = bSpliterator; 710 beforeSplit = true; 711 // The spliterator is known to be unsized before splitting if the 712 // sum of the estimates overflows. 713 unsized = aSpliterator.estimateSize() + bSpliterator.estimateSize() < 0; 714 } 715 716 @Override 717 public T_SPLITR trySplit() { 718 @SuppressWarnings("unchecked") 719 T_SPLITR ret = beforeSplit ? aSpliterator : (T_SPLITR) bSpliterator.trySplit(); 720 beforeSplit = false; 721 return ret; 722 } 723 724 @Override 725 public boolean tryAdvance(Consumer<? super T> consumer) { 726 boolean hasNext; 727 if (beforeSplit) { 728 hasNext = aSpliterator.tryAdvance(consumer); 729 if (!hasNext) { 730 beforeSplit = false; 731 hasNext = bSpliterator.tryAdvance(consumer); 732 } 733 } 734 else 735 hasNext = bSpliterator.tryAdvance(consumer); 736 return hasNext; 737 } 738 739 @Override 740 public void forEachRemaining(Consumer<? super T> consumer) { 741 if (beforeSplit) 742 aSpliterator.forEachRemaining(consumer); 743 bSpliterator.forEachRemaining(consumer); 744 } 745 746 @Override 747 public long estimateSize() { 748 if (beforeSplit) { 749 // If one or both estimates are Long.MAX_VALUE then the sum 750 // will either be Long.MAX_VALUE or overflow to a negative value 751 long size = aSpliterator.estimateSize() + bSpliterator.estimateSize(); 752 return (size >= 0) ? size : Long.MAX_VALUE; 753 } 754 else { 755 return bSpliterator.estimateSize(); 756 } 757 } 758 759 @Override characteristics()760 public int characteristics() { 761 if (beforeSplit) { 762 // Concatenation loses DISTINCT and SORTED characteristics 763 return aSpliterator.characteristics() & bSpliterator.characteristics() 764 & ~(Spliterator.DISTINCT | Spliterator.SORTED 765 | (unsized ? Spliterator.SIZED | Spliterator.SUBSIZED : 0)); 766 } 767 else { 768 return bSpliterator.characteristics(); 769 } 770 } 771 772 @Override getComparator()773 public Comparator<? super T> getComparator() { 774 if (beforeSplit) 775 throw new IllegalStateException(); 776 return bSpliterator.getComparator(); 777 } 778 779 static class OfRef<T> extends ConcatSpliterator<T, Spliterator<T>> { OfRef(Spliterator<T> aSpliterator, Spliterator<T> bSpliterator)780 OfRef(Spliterator<T> aSpliterator, Spliterator<T> bSpliterator) { 781 super(aSpliterator, bSpliterator); 782 } 783 } 784 785 private static abstract class OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>> 786 extends ConcatSpliterator<T, T_SPLITR> 787 implements Spliterator.OfPrimitive<T, T_CONS, T_SPLITR> { OfPrimitive(T_SPLITR aSpliterator, T_SPLITR bSpliterator)788 private OfPrimitive(T_SPLITR aSpliterator, T_SPLITR bSpliterator) { 789 super(aSpliterator, bSpliterator); 790 } 791 792 @Override tryAdvance(T_CONS action)793 public boolean tryAdvance(T_CONS action) { 794 boolean hasNext; 795 if (beforeSplit) { 796 hasNext = aSpliterator.tryAdvance(action); 797 if (!hasNext) { 798 beforeSplit = false; 799 hasNext = bSpliterator.tryAdvance(action); 800 } 801 } 802 else 803 hasNext = bSpliterator.tryAdvance(action); 804 return hasNext; 805 } 806 807 @Override forEachRemaining(T_CONS action)808 public void forEachRemaining(T_CONS action) { 809 if (beforeSplit) 810 aSpliterator.forEachRemaining(action); 811 bSpliterator.forEachRemaining(action); 812 } 813 } 814 815 static class OfInt 816 extends ConcatSpliterator.OfPrimitive<Integer, IntConsumer, Spliterator.OfInt> 817 implements Spliterator.OfInt { OfInt(Spliterator.OfInt aSpliterator, Spliterator.OfInt bSpliterator)818 OfInt(Spliterator.OfInt aSpliterator, Spliterator.OfInt bSpliterator) { 819 super(aSpliterator, bSpliterator); 820 } 821 } 822 823 static class OfLong 824 extends ConcatSpliterator.OfPrimitive<Long, LongConsumer, Spliterator.OfLong> 825 implements Spliterator.OfLong { OfLong(Spliterator.OfLong aSpliterator, Spliterator.OfLong bSpliterator)826 OfLong(Spliterator.OfLong aSpliterator, Spliterator.OfLong bSpliterator) { 827 super(aSpliterator, bSpliterator); 828 } 829 } 830 831 static class OfDouble 832 extends ConcatSpliterator.OfPrimitive<Double, DoubleConsumer, Spliterator.OfDouble> 833 implements Spliterator.OfDouble { OfDouble(Spliterator.OfDouble aSpliterator, Spliterator.OfDouble bSpliterator)834 OfDouble(Spliterator.OfDouble aSpliterator, Spliterator.OfDouble bSpliterator) { 835 super(aSpliterator, bSpliterator); 836 } 837 } 838 } 839 840 /** 841 * Given two Runnables, return a Runnable that executes both in sequence, 842 * even if the first throws an exception, and if both throw exceptions, add 843 * any exceptions thrown by the second as suppressed exceptions of the first. 844 */ composeWithExceptions(Runnable a, Runnable b)845 static Runnable composeWithExceptions(Runnable a, Runnable b) { 846 return new Runnable() { 847 @Override 848 public void run() { 849 try { 850 a.run(); 851 } 852 catch (Throwable e1) { 853 try { 854 b.run(); 855 } 856 catch (Throwable e2) { 857 try { 858 e1.addSuppressed(e2); 859 } catch (Throwable ignore) {} 860 } 861 throw e1; 862 } 863 b.run(); 864 } 865 }; 866 } 867 868 /** 869 * Given two streams, return a Runnable that 870 * executes both of their {@link BaseStream#close} methods in sequence, 871 * even if the first throws an exception, and if both throw exceptions, add 872 * any exceptions thrown by the second as suppressed exceptions of the first. 873 */ 874 static Runnable composedClose(BaseStream<?, ?> a, BaseStream<?, ?> b) { 875 return new Runnable() { 876 @Override 877 public void run() { 878 try { 879 a.close(); 880 } 881 catch (Throwable e1) { 882 try { 883 b.close(); 884 } 885 catch (Throwable e2) { 886 try { 887 e1.addSuppressed(e2); 888 } catch (Throwable ignore) {} 889 } 890 throw e1; 891 } 892 b.close(); 893 } 894 }; 895 } 896 } 897