Coverage Summary for Class: Streams (com.google.common.collect)
| Class | Method, % | Line, % |
|---|---|---|
| Streams | 0% (0/33) | 0% (0/171) |
| Streams$1 | 0% (0/2) | 0% (0/5) |
| Streams$1OptionalState | 0% (0/3) | 0% (0/7) |
| Streams$1Splitr | 0% (0/4) | 0% (0/10) |
| Streams$2 | 0% (0/2) | 0% (0/6) |
| Streams$2Splitr | 0% (0/4) | 0% (0/8) |
| Streams$3 | 0% (0/2) | 0% (0/6) |
| Streams$3Splitr | 0% (0/4) | 0% (0/8) |
| Streams$4 | 0% (0/2) | 0% (0/6) |
| Streams$4Splitr | 0% (0/4) | 0% (0/8) |
| Streams$5 | 0% (0/2) | 0% (0/6) |
| Streams$MapWithIndexSpliterator | 0% (0/4) | 0% (0/11) |
| Streams$TemporaryPair | 0% (0/1) | 0% (0/3) |
| Total | 0% (0/67) | 0% (0/255) |
1 /* 2 * Copyright (C) 2015 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you 5 * may not use this file except in compliance with the License. You may 6 * obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 * implied. See the License for the specific language governing 14 * permissions and limitations under the License. 15 */ 16 17 package com.google.common.collect; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 import static com.google.common.base.Preconditions.checkState; 21 22 import com.google.common.annotations.Beta; 23 import com.google.common.annotations.GwtCompatible; 24 import com.google.common.math.LongMath; 25 import com.google.errorprone.annotations.InlineMe; 26 import java.util.ArrayDeque; 27 import java.util.Collection; 28 import java.util.Deque; 29 import java.util.Iterator; 30 import java.util.OptionalDouble; 31 import java.util.OptionalInt; 32 import java.util.OptionalLong; 33 import java.util.PrimitiveIterator; 34 import java.util.Spliterator; 35 import java.util.Spliterators; 36 import java.util.Spliterators.AbstractSpliterator; 37 import java.util.function.BiConsumer; 38 import java.util.function.BiFunction; 39 import java.util.function.Consumer; 40 import java.util.function.DoubleConsumer; 41 import java.util.function.IntConsumer; 42 import java.util.function.LongConsumer; 43 import java.util.stream.BaseStream; 44 import java.util.stream.DoubleStream; 45 import java.util.stream.IntStream; 46 import java.util.stream.LongStream; 47 import java.util.stream.Stream; 48 import java.util.stream.StreamSupport; 49 import org.checkerframework.checker.nullness.qual.Nullable; 50 51 /** 52 * Static utility methods related to {@code Stream} instances. 53 * 54 * @since 21.0 55 */ 56 @GwtCompatible 57 public final class Streams { 58 /** 59 * Returns a sequential {@link Stream} of the contents of {@code iterable}, delegating to {@link 60 * Collection#stream} if possible. 61 */ 62 public static <T> Stream<T> stream(Iterable<T> iterable) { 63 return (iterable instanceof Collection) 64 ? ((Collection<T>) iterable).stream() 65 : StreamSupport.stream(iterable.spliterator(), false); 66 } 67 68 /** 69 * Returns {@link Collection#stream}. 70 * 71 * @deprecated There is no reason to use this; just invoke {@code collection.stream()} directly. 72 */ 73 @Beta 74 @Deprecated 75 @InlineMe(replacement = "collection.stream()") 76 public static <T> Stream<T> stream(Collection<T> collection) { 77 return collection.stream(); 78 } 79 80 /** 81 * Returns a sequential {@link Stream} of the remaining contents of {@code iterator}. Do not use 82 * {@code iterator} directly after passing it to this method. 83 */ 84 @Beta 85 public static <T> Stream<T> stream(Iterator<T> iterator) { 86 return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false); 87 } 88 89 /** 90 * If a value is present in {@code optional}, returns a stream containing only that element, 91 * otherwise returns an empty stream. 92 */ 93 @Beta 94 public static <T> Stream<T> stream(com.google.common.base.Optional<T> optional) { 95 return optional.isPresent() ? Stream.of(optional.get()) : Stream.empty(); 96 } 97 98 /** 99 * If a value is present in {@code optional}, returns a stream containing only that element, 100 * otherwise returns an empty stream. 101 * 102 * <p><b>Java 9 users:</b> use {@code optional.stream()} instead. 103 */ 104 @Beta 105 public static <T> Stream<T> stream(java.util.Optional<T> optional) { 106 return optional.isPresent() ? Stream.of(optional.get()) : Stream.empty(); 107 } 108 109 /** 110 * If a value is present in {@code optional}, returns a stream containing only that element, 111 * otherwise returns an empty stream. 112 * 113 * <p><b>Java 9 users:</b> use {@code optional.stream()} instead. 114 */ 115 @Beta 116 public static IntStream stream(OptionalInt optional) { 117 return optional.isPresent() ? IntStream.of(optional.getAsInt()) : IntStream.empty(); 118 } 119 120 /** 121 * If a value is present in {@code optional}, returns a stream containing only that element, 122 * otherwise returns an empty stream. 123 * 124 * <p><b>Java 9 users:</b> use {@code optional.stream()} instead. 125 */ 126 @Beta 127 public static LongStream stream(OptionalLong optional) { 128 return optional.isPresent() ? LongStream.of(optional.getAsLong()) : LongStream.empty(); 129 } 130 131 /** 132 * If a value is present in {@code optional}, returns a stream containing only that element, 133 * otherwise returns an empty stream. 134 * 135 * <p><b>Java 9 users:</b> use {@code optional.stream()} instead. 136 */ 137 @Beta 138 public static DoubleStream stream(OptionalDouble optional) { 139 return optional.isPresent() ? DoubleStream.of(optional.getAsDouble()) : DoubleStream.empty(); 140 } 141 142 private static void closeAll(BaseStream<?, ?>[] toClose) { 143 for (BaseStream<?, ?> stream : toClose) { 144 // TODO(b/80534298): Catch exceptions, rethrowing later with extras as suppressed exceptions. 145 stream.close(); 146 } 147 } 148 149 /** 150 * Returns a {@link Stream} containing the elements of the first stream, followed by the elements 151 * of the second stream, and so on. 152 * 153 * <p>This is equivalent to {@code Stream.of(streams).flatMap(stream -> stream)}, but the returned 154 * stream may perform better. 155 * 156 * @see Stream#concat(Stream, Stream) 157 */ 158 @SafeVarargs 159 public static <T> Stream<T> concat(Stream<? extends T>... streams) { 160 // TODO(lowasser): consider an implementation that can support SUBSIZED 161 boolean isParallel = false; 162 int characteristics = Spliterator.ORDERED | Spliterator.SIZED | Spliterator.NONNULL; 163 long estimatedSize = 0L; 164 ImmutableList.Builder<Spliterator<? extends T>> splitrsBuilder = 165 new ImmutableList.Builder<>(streams.length); 166 for (Stream<? extends T> stream : streams) { 167 isParallel |= stream.isParallel(); 168 Spliterator<? extends T> splitr = stream.spliterator(); 169 splitrsBuilder.add(splitr); 170 characteristics &= splitr.characteristics(); 171 estimatedSize = LongMath.saturatedAdd(estimatedSize, splitr.estimateSize()); 172 } 173 return StreamSupport.stream( 174 CollectSpliterators.flatMap( 175 splitrsBuilder.build().spliterator(), 176 splitr -> (Spliterator<T>) splitr, 177 characteristics, 178 estimatedSize), 179 isParallel) 180 .onClose(() -> closeAll(streams)); 181 } 182 183 /** 184 * Returns an {@link IntStream} containing the elements of the first stream, followed by the 185 * elements of the second stream, and so on. 186 * 187 * <p>This is equivalent to {@code Stream.of(streams).flatMapToInt(stream -> stream)}, but the 188 * returned stream may perform better. 189 * 190 * @see IntStream#concat(IntStream, IntStream) 191 */ 192 public static IntStream concat(IntStream... streams) { 193 boolean isParallel = false; 194 int characteristics = Spliterator.ORDERED | Spliterator.SIZED | Spliterator.NONNULL; 195 long estimatedSize = 0L; 196 ImmutableList.Builder<Spliterator.OfInt> splitrsBuilder = 197 new ImmutableList.Builder<>(streams.length); 198 for (IntStream stream : streams) { 199 isParallel |= stream.isParallel(); 200 Spliterator.OfInt splitr = stream.spliterator(); 201 splitrsBuilder.add(splitr); 202 characteristics &= splitr.characteristics(); 203 estimatedSize = LongMath.saturatedAdd(estimatedSize, splitr.estimateSize()); 204 } 205 return StreamSupport.intStream( 206 CollectSpliterators.flatMapToInt( 207 splitrsBuilder.build().spliterator(), 208 splitr -> splitr, 209 characteristics, 210 estimatedSize), 211 isParallel) 212 .onClose(() -> closeAll(streams)); 213 } 214 215 /** 216 * Returns a {@link LongStream} containing the elements of the first stream, followed by the 217 * elements of the second stream, and so on. 218 * 219 * <p>This is equivalent to {@code Stream.of(streams).flatMapToLong(stream -> stream)}, but the 220 * returned stream may perform better. 221 * 222 * @see LongStream#concat(LongStream, LongStream) 223 */ 224 public static LongStream concat(LongStream... streams) { 225 boolean isParallel = false; 226 int characteristics = Spliterator.ORDERED | Spliterator.SIZED | Spliterator.NONNULL; 227 long estimatedSize = 0L; 228 ImmutableList.Builder<Spliterator.OfLong> splitrsBuilder = 229 new ImmutableList.Builder<>(streams.length); 230 for (LongStream stream : streams) { 231 isParallel |= stream.isParallel(); 232 Spliterator.OfLong splitr = stream.spliterator(); 233 splitrsBuilder.add(splitr); 234 characteristics &= splitr.characteristics(); 235 estimatedSize = LongMath.saturatedAdd(estimatedSize, splitr.estimateSize()); 236 } 237 return StreamSupport.longStream( 238 CollectSpliterators.flatMapToLong( 239 splitrsBuilder.build().spliterator(), 240 splitr -> splitr, 241 characteristics, 242 estimatedSize), 243 isParallel) 244 .onClose(() -> closeAll(streams)); 245 } 246 247 /** 248 * Returns a {@link DoubleStream} containing the elements of the first stream, followed by the 249 * elements of the second stream, and so on. 250 * 251 * <p>This is equivalent to {@code Stream.of(streams).flatMapToDouble(stream -> stream)}, but the 252 * returned stream may perform better. 253 * 254 * @see DoubleStream#concat(DoubleStream, DoubleStream) 255 */ 256 public static DoubleStream concat(DoubleStream... streams) { 257 boolean isParallel = false; 258 int characteristics = Spliterator.ORDERED | Spliterator.SIZED | Spliterator.NONNULL; 259 long estimatedSize = 0L; 260 ImmutableList.Builder<Spliterator.OfDouble> splitrsBuilder = 261 new ImmutableList.Builder<>(streams.length); 262 for (DoubleStream stream : streams) { 263 isParallel |= stream.isParallel(); 264 Spliterator.OfDouble splitr = stream.spliterator(); 265 splitrsBuilder.add(splitr); 266 characteristics &= splitr.characteristics(); 267 estimatedSize = LongMath.saturatedAdd(estimatedSize, splitr.estimateSize()); 268 } 269 return StreamSupport.doubleStream( 270 CollectSpliterators.flatMapToDouble( 271 splitrsBuilder.build().spliterator(), 272 splitr -> splitr, 273 characteristics, 274 estimatedSize), 275 isParallel) 276 .onClose(() -> closeAll(streams)); 277 } 278 279 /** 280 * Returns a stream in which each element is the result of passing the corresponding element of 281 * each of {@code streamA} and {@code streamB} to {@code function}. 282 * 283 * <p>For example: 284 * 285 * <pre>{@code 286 * Streams.zip( 287 * Stream.of("foo1", "foo2", "foo3"), 288 * Stream.of("bar1", "bar2"), 289 * (arg1, arg2) -> arg1 + ":" + arg2) 290 * }</pre> 291 * 292 * <p>will return {@code Stream.of("foo1:bar1", "foo2:bar2")}. 293 * 294 * <p>The resulting stream will only be as long as the shorter of the two input streams; if one 295 * stream is longer, its extra elements will be ignored. 296 * 297 * <p>Note that if you are calling {@link Stream#forEach} on the resulting stream, you might want 298 * to consider using {@link #forEachPair} instead of this method. 299 * 300 * <p><b>Performance note:</b> The resulting stream is not <a 301 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a>. 302 * This may harm parallel performance. 303 */ 304 @Beta 305 public static <A, B, R> Stream<R> zip( 306 Stream<A> streamA, Stream<B> streamB, BiFunction<? super A, ? super B, R> function) { 307 checkNotNull(streamA); 308 checkNotNull(streamB); 309 checkNotNull(function); 310 boolean isParallel = streamA.isParallel() || streamB.isParallel(); // same as Stream.concat 311 Spliterator<A> splitrA = streamA.spliterator(); 312 Spliterator<B> splitrB = streamB.spliterator(); 313 int characteristics = 314 splitrA.characteristics() 315 & splitrB.characteristics() 316 & (Spliterator.SIZED | Spliterator.ORDERED); 317 Iterator<A> itrA = Spliterators.iterator(splitrA); 318 Iterator<B> itrB = Spliterators.iterator(splitrB); 319 return StreamSupport.stream( 320 new AbstractSpliterator<R>( 321 Math.min(splitrA.estimateSize(), splitrB.estimateSize()), characteristics) { 322 @Override 323 public boolean tryAdvance(Consumer<? super R> action) { 324 if (itrA.hasNext() && itrB.hasNext()) { 325 action.accept(function.apply(itrA.next(), itrB.next())); 326 return true; 327 } 328 return false; 329 } 330 }, 331 isParallel) 332 .onClose(streamA::close) 333 .onClose(streamB::close); 334 } 335 336 /** 337 * Invokes {@code consumer} once for each pair of <i>corresponding</i> elements in {@code streamA} 338 * and {@code streamB}. If one stream is longer than the other, the extra elements are silently 339 * ignored. Elements passed to the consumer are guaranteed to come from the same position in their 340 * respective source streams. For example: 341 * 342 * <pre>{@code 343 * Streams.forEachPair( 344 * Stream.of("foo1", "foo2", "foo3"), 345 * Stream.of("bar1", "bar2"), 346 * (arg1, arg2) -> System.out.println(arg1 + ":" + arg2) 347 * }</pre> 348 * 349 * <p>will print: 350 * 351 * <pre>{@code 352 * foo1:bar1 353 * foo2:bar2 354 * }</pre> 355 * 356 * <p><b>Warning:</b> If either supplied stream is a parallel stream, the same correspondence 357 * between elements will be made, but the order in which those pairs of elements are passed to the 358 * consumer is <i>not</i> defined. 359 * 360 * <p>Note that many usages of this method can be replaced with simpler calls to {@link #zip}. 361 * This method behaves equivalently to {@linkplain #zip zipping} the stream elements into 362 * temporary pair objects and then using {@link Stream#forEach} on that stream. 363 * 364 * @since 22.0 365 */ 366 @Beta 367 public static <A, B> void forEachPair( 368 Stream<A> streamA, Stream<B> streamB, BiConsumer<? super A, ? super B> consumer) { 369 checkNotNull(consumer); 370 371 if (streamA.isParallel() || streamB.isParallel()) { 372 zip(streamA, streamB, TemporaryPair::new).forEach(pair -> consumer.accept(pair.a, pair.b)); 373 } else { 374 Iterator<A> iterA = streamA.iterator(); 375 Iterator<B> iterB = streamB.iterator(); 376 while (iterA.hasNext() && iterB.hasNext()) { 377 consumer.accept(iterA.next(), iterB.next()); 378 } 379 } 380 } 381 382 // Use this carefully - it doesn't implement value semantics 383 private static class TemporaryPair<A, B> { 384 final A a; 385 final B b; 386 387 TemporaryPair(A a, B b) { 388 this.a = a; 389 this.b = b; 390 } 391 } 392 393 /** 394 * Returns a stream consisting of the results of applying the given function to the elements of 395 * {@code stream} and their indices in the stream. For example, 396 * 397 * <pre>{@code 398 * mapWithIndex( 399 * Stream.of("a", "b", "c"), 400 * (str, index) -> str + ":" + index) 401 * }</pre> 402 * 403 * <p>would return {@code Stream.of("a:0", "b:1", "c:2")}. 404 * 405 * <p>The resulting stream is <a 406 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 407 * if and only if {@code stream} was efficiently splittable and its underlying spliterator 408 * reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream 409 * comes from a data structure supporting efficient indexed random access, typically an array or 410 * list. 411 * 412 * <p>The order of the resulting stream is defined if and only if the order of the original stream 413 * was defined. 414 */ 415 @Beta 416 public static <T, R> Stream<R> mapWithIndex( 417 Stream<T> stream, FunctionWithIndex<? super T, ? extends R> function) { 418 checkNotNull(stream); 419 checkNotNull(function); 420 boolean isParallel = stream.isParallel(); 421 Spliterator<T> fromSpliterator = stream.spliterator(); 422 423 if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 424 Iterator<T> fromIterator = Spliterators.iterator(fromSpliterator); 425 return StreamSupport.stream( 426 new AbstractSpliterator<R>( 427 fromSpliterator.estimateSize(), 428 fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) { 429 long index = 0; 430 431 @Override 432 public boolean tryAdvance(Consumer<? super R> action) { 433 if (fromIterator.hasNext()) { 434 action.accept(function.apply(fromIterator.next(), index++)); 435 return true; 436 } 437 return false; 438 } 439 }, 440 isParallel) 441 .onClose(stream::close); 442 } 443 class Splitr extends MapWithIndexSpliterator<Spliterator<T>, R, Splitr> implements Consumer<T> { 444 @Nullable T holder; 445 446 Splitr(Spliterator<T> splitr, long index) { 447 super(splitr, index); 448 } 449 450 @Override 451 public void accept(@Nullable T t) { 452 this.holder = t; 453 } 454 455 @Override 456 public boolean tryAdvance(Consumer<? super R> action) { 457 if (fromSpliterator.tryAdvance(this)) { 458 try { 459 action.accept(function.apply(holder, index++)); 460 return true; 461 } finally { 462 holder = null; 463 } 464 } 465 return false; 466 } 467 468 @Override 469 Splitr createSplit(Spliterator<T> from, long i) { 470 return new Splitr(from, i); 471 } 472 } 473 return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close); 474 } 475 476 /** 477 * Returns a stream consisting of the results of applying the given function to the elements of 478 * {@code stream} and their indexes in the stream. For example, 479 * 480 * <pre>{@code 481 * mapWithIndex( 482 * IntStream.of(0, 1, 2), 483 * (i, index) -> i + ":" + index) 484 * }</pre> 485 * 486 * <p>...would return {@code Stream.of("0:0", "1:1", "2:2")}. 487 * 488 * <p>The resulting stream is <a 489 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 490 * if and only if {@code stream} was efficiently splittable and its underlying spliterator 491 * reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream 492 * comes from a data structure supporting efficient indexed random access, typically an array or 493 * list. 494 * 495 * <p>The order of the resulting stream is defined if and only if the order of the original stream 496 * was defined. 497 */ 498 @Beta 499 public static <R> Stream<R> mapWithIndex(IntStream stream, IntFunctionWithIndex<R> function) { 500 checkNotNull(stream); 501 checkNotNull(function); 502 boolean isParallel = stream.isParallel(); 503 Spliterator.OfInt fromSpliterator = stream.spliterator(); 504 505 if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 506 PrimitiveIterator.OfInt fromIterator = Spliterators.iterator(fromSpliterator); 507 return StreamSupport.stream( 508 new AbstractSpliterator<R>( 509 fromSpliterator.estimateSize(), 510 fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) { 511 long index = 0; 512 513 @Override 514 public boolean tryAdvance(Consumer<? super R> action) { 515 if (fromIterator.hasNext()) { 516 action.accept(function.apply(fromIterator.nextInt(), index++)); 517 return true; 518 } 519 return false; 520 } 521 }, 522 isParallel) 523 .onClose(stream::close); 524 } 525 class Splitr extends MapWithIndexSpliterator<Spliterator.OfInt, R, Splitr> 526 implements IntConsumer, Spliterator<R> { 527 int holder; 528 529 Splitr(Spliterator.OfInt splitr, long index) { 530 super(splitr, index); 531 } 532 533 @Override 534 public void accept(int t) { 535 this.holder = t; 536 } 537 538 @Override 539 public boolean tryAdvance(Consumer<? super R> action) { 540 if (fromSpliterator.tryAdvance(this)) { 541 action.accept(function.apply(holder, index++)); 542 return true; 543 } 544 return false; 545 } 546 547 @Override 548 Splitr createSplit(Spliterator.OfInt from, long i) { 549 return new Splitr(from, i); 550 } 551 } 552 return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close); 553 } 554 555 /** 556 * Returns a stream consisting of the results of applying the given function to the elements of 557 * {@code stream} and their indexes in the stream. For example, 558 * 559 * <pre>{@code 560 * mapWithIndex( 561 * LongStream.of(0, 1, 2), 562 * (i, index) -> i + ":" + index) 563 * }</pre> 564 * 565 * <p>...would return {@code Stream.of("0:0", "1:1", "2:2")}. 566 * 567 * <p>The resulting stream is <a 568 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 569 * if and only if {@code stream} was efficiently splittable and its underlying spliterator 570 * reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream 571 * comes from a data structure supporting efficient indexed random access, typically an array or 572 * list. 573 * 574 * <p>The order of the resulting stream is defined if and only if the order of the original stream 575 * was defined. 576 */ 577 @Beta 578 public static <R> Stream<R> mapWithIndex(LongStream stream, LongFunctionWithIndex<R> function) { 579 checkNotNull(stream); 580 checkNotNull(function); 581 boolean isParallel = stream.isParallel(); 582 Spliterator.OfLong fromSpliterator = stream.spliterator(); 583 584 if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 585 PrimitiveIterator.OfLong fromIterator = Spliterators.iterator(fromSpliterator); 586 return StreamSupport.stream( 587 new AbstractSpliterator<R>( 588 fromSpliterator.estimateSize(), 589 fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) { 590 long index = 0; 591 592 @Override 593 public boolean tryAdvance(Consumer<? super R> action) { 594 if (fromIterator.hasNext()) { 595 action.accept(function.apply(fromIterator.nextLong(), index++)); 596 return true; 597 } 598 return false; 599 } 600 }, 601 isParallel) 602 .onClose(stream::close); 603 } 604 class Splitr extends MapWithIndexSpliterator<Spliterator.OfLong, R, Splitr> 605 implements LongConsumer, Spliterator<R> { 606 long holder; 607 608 Splitr(Spliterator.OfLong splitr, long index) { 609 super(splitr, index); 610 } 611 612 @Override 613 public void accept(long t) { 614 this.holder = t; 615 } 616 617 @Override 618 public boolean tryAdvance(Consumer<? super R> action) { 619 if (fromSpliterator.tryAdvance(this)) { 620 action.accept(function.apply(holder, index++)); 621 return true; 622 } 623 return false; 624 } 625 626 @Override 627 Splitr createSplit(Spliterator.OfLong from, long i) { 628 return new Splitr(from, i); 629 } 630 } 631 return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close); 632 } 633 634 /** 635 * Returns a stream consisting of the results of applying the given function to the elements of 636 * {@code stream} and their indexes in the stream. For example, 637 * 638 * <pre>{@code 639 * mapWithIndex( 640 * DoubleStream.of(0, 1, 2), 641 * (x, index) -> x + ":" + index) 642 * }</pre> 643 * 644 * <p>...would return {@code Stream.of("0.0:0", "1.0:1", "2.0:2")}. 645 * 646 * <p>The resulting stream is <a 647 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 648 * if and only if {@code stream} was efficiently splittable and its underlying spliterator 649 * reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream 650 * comes from a data structure supporting efficient indexed random access, typically an array or 651 * list. 652 * 653 * <p>The order of the resulting stream is defined if and only if the order of the original stream 654 * was defined. 655 */ 656 @Beta 657 public static <R> Stream<R> mapWithIndex( 658 DoubleStream stream, DoubleFunctionWithIndex<R> function) { 659 checkNotNull(stream); 660 checkNotNull(function); 661 boolean isParallel = stream.isParallel(); 662 Spliterator.OfDouble fromSpliterator = stream.spliterator(); 663 664 if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 665 PrimitiveIterator.OfDouble fromIterator = Spliterators.iterator(fromSpliterator); 666 return StreamSupport.stream( 667 new AbstractSpliterator<R>( 668 fromSpliterator.estimateSize(), 669 fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) { 670 long index = 0; 671 672 @Override 673 public boolean tryAdvance(Consumer<? super R> action) { 674 if (fromIterator.hasNext()) { 675 action.accept(function.apply(fromIterator.nextDouble(), index++)); 676 return true; 677 } 678 return false; 679 } 680 }, 681 isParallel) 682 .onClose(stream::close); 683 } 684 class Splitr extends MapWithIndexSpliterator<Spliterator.OfDouble, R, Splitr> 685 implements DoubleConsumer, Spliterator<R> { 686 double holder; 687 688 Splitr(Spliterator.OfDouble splitr, long index) { 689 super(splitr, index); 690 } 691 692 @Override 693 public void accept(double t) { 694 this.holder = t; 695 } 696 697 @Override 698 public boolean tryAdvance(Consumer<? super R> action) { 699 if (fromSpliterator.tryAdvance(this)) { 700 action.accept(function.apply(holder, index++)); 701 return true; 702 } 703 return false; 704 } 705 706 @Override 707 Splitr createSplit(Spliterator.OfDouble from, long i) { 708 return new Splitr(from, i); 709 } 710 } 711 return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close); 712 } 713 714 /** 715 * An analogue of {@link java.util.function.Function} also accepting an index. 716 * 717 * <p>This interface is only intended for use by callers of {@link #mapWithIndex(Stream, 718 * FunctionWithIndex)}. 719 * 720 * @since 21.0 721 */ 722 @Beta 723 public interface FunctionWithIndex<T, R> { 724 /** Applies this function to the given argument and its index within a stream. */ 725 R apply(T from, long index); 726 } 727 728 private abstract static class MapWithIndexSpliterator< 729 F extends Spliterator<?>, R, S extends MapWithIndexSpliterator<F, R, S>> 730 implements Spliterator<R> { 731 final F fromSpliterator; 732 long index; 733 734 MapWithIndexSpliterator(F fromSpliterator, long index) { 735 this.fromSpliterator = fromSpliterator; 736 this.index = index; 737 } 738 739 abstract S createSplit(F from, long i); 740 741 @Override 742 public S trySplit() { 743 @SuppressWarnings("unchecked") 744 F split = (F) fromSpliterator.trySplit(); 745 if (split == null) { 746 return null; 747 } 748 S result = createSplit(split, index); 749 this.index += split.getExactSizeIfKnown(); 750 return result; 751 } 752 753 @Override 754 public long estimateSize() { 755 return fromSpliterator.estimateSize(); 756 } 757 758 @Override 759 public int characteristics() { 760 return fromSpliterator.characteristics() 761 & (Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED); 762 } 763 } 764 765 /** 766 * An analogue of {@link java.util.function.IntFunction} also accepting an index. 767 * 768 * <p>This interface is only intended for use by callers of {@link #mapWithIndex(IntStream, 769 * IntFunctionWithIndex)}. 770 * 771 * @since 21.0 772 */ 773 @Beta 774 public interface IntFunctionWithIndex<R> { 775 /** Applies this function to the given argument and its index within a stream. */ 776 R apply(int from, long index); 777 } 778 779 /** 780 * An analogue of {@link java.util.function.LongFunction} also accepting an index. 781 * 782 * <p>This interface is only intended for use by callers of {@link #mapWithIndex(LongStream, 783 * LongFunctionWithIndex)}. 784 * 785 * @since 21.0 786 */ 787 @Beta 788 public interface LongFunctionWithIndex<R> { 789 /** Applies this function to the given argument and its index within a stream. */ 790 R apply(long from, long index); 791 } 792 793 /** 794 * An analogue of {@link java.util.function.DoubleFunction} also accepting an index. 795 * 796 * <p>This interface is only intended for use by callers of {@link #mapWithIndex(DoubleStream, 797 * DoubleFunctionWithIndex)}. 798 * 799 * @since 21.0 800 */ 801 @Beta 802 public interface DoubleFunctionWithIndex<R> { 803 /** Applies this function to the given argument and its index within a stream. */ 804 R apply(double from, long index); 805 } 806 807 /** 808 * Returns the last element of the specified stream, or {@link java.util.Optional#empty} if the 809 * stream is empty. 810 * 811 * <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This 812 * method's runtime will be between O(log n) and O(n), performing better on <a 813 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 814 * streams. 815 * 816 * <p>If the stream has nondeterministic order, this has equivalent semantics to {@link 817 * Stream#findAny} (which you might as well use). 818 * 819 * @see Stream#findFirst() 820 * @throws NullPointerException if the last element of the stream is null 821 */ 822 @Beta 823 public static <T> java.util.Optional<T> findLast(Stream<T> stream) { 824 class OptionalState { 825 boolean set = false; 826 T value = null; 827 828 void set(@Nullable T value) { 829 this.set = true; 830 this.value = value; 831 } 832 833 T get() { 834 checkState(set); 835 return value; 836 } 837 } 838 OptionalState state = new OptionalState(); 839 840 Deque<Spliterator<T>> splits = new ArrayDeque<>(); 841 splits.addLast(stream.spliterator()); 842 843 while (!splits.isEmpty()) { 844 Spliterator<T> spliterator = splits.removeLast(); 845 846 if (spliterator.getExactSizeIfKnown() == 0) { 847 continue; // drop this split 848 } 849 850 // Many spliterators will have trySplits that are SUBSIZED even if they are not themselves 851 // SUBSIZED. 852 if (spliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 853 // we can drill down to exactly the smallest nonempty spliterator 854 while (true) { 855 Spliterator<T> prefix = spliterator.trySplit(); 856 if (prefix == null || prefix.getExactSizeIfKnown() == 0) { 857 break; 858 } else if (spliterator.getExactSizeIfKnown() == 0) { 859 spliterator = prefix; 860 break; 861 } 862 } 863 864 // spliterator is known to be nonempty now 865 spliterator.forEachRemaining(state::set); 866 return java.util.Optional.of(state.get()); 867 } 868 869 Spliterator<T> prefix = spliterator.trySplit(); 870 if (prefix == null || prefix.getExactSizeIfKnown() == 0) { 871 // we can't split this any further 872 spliterator.forEachRemaining(state::set); 873 if (state.set) { 874 return java.util.Optional.of(state.get()); 875 } 876 // fall back to the last split 877 continue; 878 } 879 splits.addLast(prefix); 880 splits.addLast(spliterator); 881 } 882 return java.util.Optional.empty(); 883 } 884 885 /** 886 * Returns the last element of the specified stream, or {@link OptionalInt#empty} if the stream is 887 * empty. 888 * 889 * <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This 890 * method's runtime will be between O(log n) and O(n), performing better on <a 891 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 892 * streams. 893 * 894 * @see IntStream#findFirst() 895 * @throws NullPointerException if the last element of the stream is null 896 */ 897 @Beta 898 public static OptionalInt findLast(IntStream stream) { 899 // findLast(Stream) does some allocation, so we might as well box some more 900 java.util.Optional<Integer> boxedLast = findLast(stream.boxed()); 901 return boxedLast.map(OptionalInt::of).orElseGet(OptionalInt::empty); 902 } 903 904 /** 905 * Returns the last element of the specified stream, or {@link OptionalLong#empty} if the stream 906 * is empty. 907 * 908 * <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This 909 * method's runtime will be between O(log n) and O(n), performing better on <a 910 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 911 * streams. 912 * 913 * @see LongStream#findFirst() 914 * @throws NullPointerException if the last element of the stream is null 915 */ 916 @Beta 917 public static OptionalLong findLast(LongStream stream) { 918 // findLast(Stream) does some allocation, so we might as well box some more 919 java.util.Optional<Long> boxedLast = findLast(stream.boxed()); 920 return boxedLast.map(OptionalLong::of).orElseGet(OptionalLong::empty); 921 } 922 923 /** 924 * Returns the last element of the specified stream, or {@link OptionalDouble#empty} if the stream 925 * is empty. 926 * 927 * <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This 928 * method's runtime will be between O(log n) and O(n), performing better on <a 929 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 930 * streams. 931 * 932 * @see DoubleStream#findFirst() 933 * @throws NullPointerException if the last element of the stream is null 934 */ 935 @Beta 936 public static OptionalDouble findLast(DoubleStream stream) { 937 // findLast(Stream) does some allocation, so we might as well box some more 938 java.util.Optional<Double> boxedLast = findLast(stream.boxed()); 939 return boxedLast.map(OptionalDouble::of).orElseGet(OptionalDouble::empty); 940 } 941 942 private Streams() {} 943 }