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