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