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 * <pre>{@code 314 * Streams.zip( 315 * Stream.of("foo1", "foo2", "foo3"), 316 * Stream.of("bar1", "bar2"), 317 * (arg1, arg2) -> arg1 + ":" + arg2) 318 * }</pre> 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 * <pre>{@code 372 * Streams.forEachPair( 373 * Stream.of("foo1", "foo2", "foo3"), 374 * Stream.of("bar1", "bar2"), 375 * (arg1, arg2) -> System.out.println(arg1 + ":" + arg2) 376 * }</pre> 377 * 378 * <p>will print: 379 * 380 * <pre>{@code 381 * foo1:bar1 382 * foo2:bar2 383 * }</pre> 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 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 * <pre>{@code 427 * mapWithIndex( 428 * Stream.of("a", "b", "c"), 429 * (e, index) -> index + ":" + e) 430 * }</pre> 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 class Splitr extends MapWithIndexSpliterator<Spliterator<T>, R, Splitr> implements Consumer<T> { 472 @Nullable T holder; 473 474 Splitr(Spliterator<T> splitr, long index) { 475 super(splitr, index); 476 } 477 478 @Override 479 public void accept(@ParametricNullness T t) { 480 this.holder = t; 481 } 482 483 @Override 484 public boolean tryAdvance(Consumer<? super R> action) { 485 if (fromSpliterator.tryAdvance(this)) { 486 try { 487 // The cast is safe because tryAdvance puts a T into `holder`. 488 action.accept(function.apply(uncheckedCastNullableTToT(holder), index++)); 489 return true; 490 } finally { 491 holder = null; 492 } 493 } 494 return false; 495 } 496 497 @Override 498 Splitr createSplit(Spliterator<T> from, long i) { 499 return new Splitr(from, i); 500 } 501 } 502 return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close); 503 } 504 505 /** 506 * Returns a stream consisting of the results of applying the given function to the elements of 507 * {@code stream} and their indexes in the stream. For example, 508 * 509 * <pre>{@code 510 * mapWithIndex( 511 * IntStream.of(10, 11, 12), 512 * (e, index) -> index + ":" + e) 513 * }</pre> 514 * 515 * <p>...would return {@code Stream.of("0:10", "1:11", "2:12")}. 516 * 517 * <p>The resulting stream is <a 518 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 519 * if and only if {@code stream} was efficiently splittable and its underlying spliterator 520 * reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream 521 * comes from a data structure supporting efficient indexed random access, typically an array or 522 * list. 523 * 524 * <p>The order of the resulting stream is defined if and only if the order of the original stream 525 * was defined. 526 */ 527 public static <R extends @Nullable Object> Stream<R> mapWithIndex( 528 IntStream stream, IntFunctionWithIndex<R> function) { 529 checkNotNull(stream); 530 checkNotNull(function); 531 boolean isParallel = stream.isParallel(); 532 Spliterator.OfInt fromSpliterator = stream.spliterator(); 533 534 if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 535 PrimitiveIterator.OfInt fromIterator = Spliterators.iterator(fromSpliterator); 536 return StreamSupport.stream( 537 new AbstractSpliterator<R>( 538 fromSpliterator.estimateSize(), 539 fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) { 540 long index = 0; 541 542 @Override 543 public boolean tryAdvance(Consumer<? super R> action) { 544 if (fromIterator.hasNext()) { 545 action.accept(function.apply(fromIterator.nextInt(), index++)); 546 return true; 547 } 548 return false; 549 } 550 }, 551 isParallel) 552 .onClose(stream::close); 553 } 554 class Splitr extends MapWithIndexSpliterator<Spliterator.OfInt, R, Splitr> 555 implements IntConsumer, Spliterator<R> { 556 int holder; 557 558 Splitr(Spliterator.OfInt splitr, long index) { 559 super(splitr, index); 560 } 561 562 @Override 563 public void accept(int t) { 564 this.holder = t; 565 } 566 567 @Override 568 public boolean tryAdvance(Consumer<? super R> action) { 569 if (fromSpliterator.tryAdvance(this)) { 570 action.accept(function.apply(holder, index++)); 571 return true; 572 } 573 return false; 574 } 575 576 @Override 577 Splitr createSplit(Spliterator.OfInt from, long i) { 578 return new Splitr(from, i); 579 } 580 } 581 return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close); 582 } 583 584 /** 585 * Returns a stream consisting of the results of applying the given function to the elements of 586 * {@code stream} and their indexes in the stream. For example, 587 * 588 * <pre>{@code 589 * mapWithIndex( 590 * LongStream.of(10, 11, 12), 591 * (e, index) -> index + ":" + e) 592 * }</pre> 593 * 594 * <p>...would return {@code Stream.of("0:10", "1:11", "2:12")}. 595 * 596 * <p>The resulting stream is <a 597 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 598 * if and only if {@code stream} was efficiently splittable and its underlying spliterator 599 * reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream 600 * comes from a data structure supporting efficient indexed random access, typically an array or 601 * list. 602 * 603 * <p>The order of the resulting stream is defined if and only if the order of the original stream 604 * was defined. 605 */ 606 public static <R extends @Nullable Object> Stream<R> mapWithIndex( 607 LongStream stream, LongFunctionWithIndex<R> function) { 608 checkNotNull(stream); 609 checkNotNull(function); 610 boolean isParallel = stream.isParallel(); 611 Spliterator.OfLong fromSpliterator = stream.spliterator(); 612 613 if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 614 PrimitiveIterator.OfLong fromIterator = Spliterators.iterator(fromSpliterator); 615 return StreamSupport.stream( 616 new AbstractSpliterator<R>( 617 fromSpliterator.estimateSize(), 618 fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) { 619 long index = 0; 620 621 @Override 622 public boolean tryAdvance(Consumer<? super R> action) { 623 if (fromIterator.hasNext()) { 624 action.accept(function.apply(fromIterator.nextLong(), index++)); 625 return true; 626 } 627 return false; 628 } 629 }, 630 isParallel) 631 .onClose(stream::close); 632 } 633 class Splitr extends MapWithIndexSpliterator<Spliterator.OfLong, R, Splitr> 634 implements LongConsumer, Spliterator<R> { 635 long holder; 636 637 Splitr(Spliterator.OfLong splitr, long index) { 638 super(splitr, index); 639 } 640 641 @Override 642 public void accept(long t) { 643 this.holder = t; 644 } 645 646 @Override 647 public boolean tryAdvance(Consumer<? super R> action) { 648 if (fromSpliterator.tryAdvance(this)) { 649 action.accept(function.apply(holder, index++)); 650 return true; 651 } 652 return false; 653 } 654 655 @Override 656 Splitr createSplit(Spliterator.OfLong from, long i) { 657 return new Splitr(from, i); 658 } 659 } 660 return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close); 661 } 662 663 /** 664 * Returns a stream consisting of the results of applying the given function to the elements of 665 * {@code stream} and their indexes in the stream. For example, 666 * 667 * <pre>{@code 668 * mapWithIndex( 669 * DoubleStream.of(0.0, 1.0, 2.0) 670 * (e, index) -> index + ":" + e) 671 * }</pre> 672 * 673 * <p>...would return {@code Stream.of("0:0.0", "1:1.0", "2:2.0")}. 674 * 675 * <p>The resulting stream is <a 676 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 677 * if and only if {@code stream} was efficiently splittable and its underlying spliterator 678 * reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream 679 * comes from a data structure supporting efficient indexed random access, typically an array or 680 * list. 681 * 682 * <p>The order of the resulting stream is defined if and only if the order of the original stream 683 * was defined. 684 */ 685 public static <R extends @Nullable Object> Stream<R> mapWithIndex( 686 DoubleStream stream, DoubleFunctionWithIndex<R> function) { 687 checkNotNull(stream); 688 checkNotNull(function); 689 boolean isParallel = stream.isParallel(); 690 Spliterator.OfDouble fromSpliterator = stream.spliterator(); 691 692 if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 693 PrimitiveIterator.OfDouble fromIterator = Spliterators.iterator(fromSpliterator); 694 return StreamSupport.stream( 695 new AbstractSpliterator<R>( 696 fromSpliterator.estimateSize(), 697 fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) { 698 long index = 0; 699 700 @Override 701 public boolean tryAdvance(Consumer<? super R> action) { 702 if (fromIterator.hasNext()) { 703 action.accept(function.apply(fromIterator.nextDouble(), index++)); 704 return true; 705 } 706 return false; 707 } 708 }, 709 isParallel) 710 .onClose(stream::close); 711 } 712 class Splitr extends MapWithIndexSpliterator<Spliterator.OfDouble, R, Splitr> 713 implements DoubleConsumer, Spliterator<R> { 714 double holder; 715 716 Splitr(Spliterator.OfDouble splitr, long index) { 717 super(splitr, index); 718 } 719 720 @Override 721 public void accept(double t) { 722 this.holder = t; 723 } 724 725 @Override 726 public boolean tryAdvance(Consumer<? super R> action) { 727 if (fromSpliterator.tryAdvance(this)) { 728 action.accept(function.apply(holder, index++)); 729 return true; 730 } 731 return false; 732 } 733 734 @Override 735 Splitr createSplit(Spliterator.OfDouble from, long i) { 736 return new Splitr(from, i); 737 } 738 } 739 return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close); 740 } 741 742 /** 743 * An analogue of {@link java.util.function.Function} also accepting an index. 744 * 745 * <p>This interface is only intended for use by callers of {@link #mapWithIndex(Stream, 746 * FunctionWithIndex)}. 747 * 748 * @since 21.0 (but only since 33.4.0 in the Android flavor) 749 */ 750 public interface FunctionWithIndex<T extends @Nullable Object, R extends @Nullable Object> { 751 /** Applies this function to the given argument and its index within a stream. */ 752 @ParametricNullness 753 R apply(@ParametricNullness T from, long index); 754 } 755 756 private abstract static class MapWithIndexSpliterator< 757 F extends Spliterator<?>, 758 R extends @Nullable Object, 759 S extends MapWithIndexSpliterator<F, R, S>> 760 implements Spliterator<R> { 761 final F fromSpliterator; 762 long index; 763 764 MapWithIndexSpliterator(F fromSpliterator, long index) { 765 this.fromSpliterator = fromSpliterator; 766 this.index = index; 767 } 768 769 abstract S createSplit(F from, long i); 770 771 @Override 772 public @Nullable S trySplit() { 773 Spliterator<?> splitOrNull = fromSpliterator.trySplit(); 774 if (splitOrNull == null) { 775 return null; 776 } 777 @SuppressWarnings("unchecked") 778 F split = (F) splitOrNull; 779 S result = createSplit(split, index); 780 this.index += split.getExactSizeIfKnown(); 781 return result; 782 } 783 784 @Override 785 public long estimateSize() { 786 return fromSpliterator.estimateSize(); 787 } 788 789 @Override 790 public int characteristics() { 791 return fromSpliterator.characteristics() 792 & (Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED); 793 } 794 } 795 796 /** 797 * An analogue of {@link java.util.function.IntFunction} also accepting an index. 798 * 799 * <p>This interface is only intended for use by callers of {@link #mapWithIndex(IntStream, 800 * IntFunctionWithIndex)}. 801 * 802 * @since 21.0 (but only since 33.4.0 in the Android flavor) 803 */ 804 public interface IntFunctionWithIndex<R extends @Nullable Object> { 805 /** Applies this function to the given argument and its index within a stream. */ 806 @ParametricNullness 807 R apply(int from, long index); 808 } 809 810 /** 811 * An analogue of {@link java.util.function.LongFunction} also accepting an index. 812 * 813 * <p>This interface is only intended for use by callers of {@link #mapWithIndex(LongStream, 814 * LongFunctionWithIndex)}. 815 * 816 * @since 21.0 (but only since 33.4.0 in the Android flavor) 817 */ 818 public interface LongFunctionWithIndex<R extends @Nullable Object> { 819 /** Applies this function to the given argument and its index within a stream. */ 820 @ParametricNullness 821 R apply(long from, long index); 822 } 823 824 /** 825 * An analogue of {@link java.util.function.DoubleFunction} also accepting an index. 826 * 827 * <p>This interface is only intended for use by callers of {@link #mapWithIndex(DoubleStream, 828 * DoubleFunctionWithIndex)}. 829 * 830 * @since 21.0 (but only since 33.4.0 in the Android flavor) 831 */ 832 public interface DoubleFunctionWithIndex<R extends @Nullable Object> { 833 /** Applies this function to the given argument and its index within a stream. */ 834 @ParametricNullness 835 R apply(double from, long index); 836 } 837 838 /** 839 * Returns the last element of the specified stream, or {@link java.util.Optional#empty} if the 840 * stream is empty. 841 * 842 * <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This 843 * method's runtime will be between O(log n) and O(n), performing better on <a 844 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 845 * streams. 846 * 847 * <p>If the stream has nondeterministic order, this has equivalent semantics to {@link 848 * Stream#findAny} (which you might as well use). 849 * 850 * @see Stream#findFirst() 851 * @throws NullPointerException if the last element of the stream is null 852 */ 853 /* 854 * By declaring <T> instead of <T extends @Nullable Object>, we declare this method as requiring a 855 * stream whose elements are non-null. However, the method goes out of its way to still handle 856 * nulls in the stream. This means that the method can safely be used with a stream that contains 857 * nulls as long as the *last* element is *not* null. 858 * 859 * (To "go out of its way," the method tracks a `set` bit so that it can distinguish "the final 860 * split has a last element of null, so throw NPE" from "the final split was empty, so look for an 861 * element in the prior one.") 862 */ 863 public static <T> java.util.Optional<T> findLast(Stream<T> stream) { 864 class OptionalState { 865 boolean set = false; 866 @Nullable T value = null; 867 868 void set(T value) { 869 this.set = true; 870 this.value = value; 871 } 872 873 T get() { 874 /* 875 * requireNonNull is safe because we call get() only if we've previously called set(). 876 * 877 * (For further discussion of nullness, see the comment above the method.) 878 */ 879 return requireNonNull(value); 880 } 881 } 882 OptionalState state = new OptionalState(); 883 884 Deque<Spliterator<T>> splits = new ArrayDeque<>(); 885 splits.addLast(stream.spliterator()); 886 887 while (!splits.isEmpty()) { 888 Spliterator<T> spliterator = splits.removeLast(); 889 890 if (spliterator.getExactSizeIfKnown() == 0) { 891 continue; // drop this split 892 } 893 894 // Many spliterators will have trySplits that are SUBSIZED even if they are not themselves 895 // SUBSIZED. 896 if (spliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 897 // we can drill down to exactly the smallest nonempty spliterator 898 while (true) { 899 Spliterator<T> prefix = spliterator.trySplit(); 900 if (prefix == null || prefix.getExactSizeIfKnown() == 0) { 901 break; 902 } else if (spliterator.getExactSizeIfKnown() == 0) { 903 spliterator = prefix; 904 break; 905 } 906 } 907 908 // spliterator is known to be nonempty now 909 spliterator.forEachRemaining(state::set); 910 return java.util.Optional.of(state.get()); 911 } 912 913 Spliterator<T> prefix = spliterator.trySplit(); 914 if (prefix == null || prefix.getExactSizeIfKnown() == 0) { 915 // we can't split this any further 916 spliterator.forEachRemaining(state::set); 917 if (state.set) { 918 return java.util.Optional.of(state.get()); 919 } 920 // fall back to the last split 921 continue; 922 } 923 splits.addLast(prefix); 924 splits.addLast(spliterator); 925 } 926 return java.util.Optional.empty(); 927 } 928 929 /** 930 * Returns the last element of the specified stream, or {@link OptionalInt#empty} if the stream is 931 * empty. 932 * 933 * <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This 934 * method's runtime will be between O(log n) and O(n), performing better on <a 935 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 936 * streams. 937 * 938 * @see IntStream#findFirst() 939 * @throws NullPointerException if the last element of the stream is null 940 */ 941 public static OptionalInt findLast(IntStream stream) { 942 // findLast(Stream) does some allocation, so we might as well box some more 943 java.util.Optional<Integer> boxedLast = findLast(stream.boxed()); 944 return boxedLast.map(OptionalInt::of).orElse(OptionalInt.empty()); 945 } 946 947 /** 948 * Returns the last element of the specified stream, or {@link OptionalLong#empty} if the stream 949 * is empty. 950 * 951 * <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This 952 * method's runtime will be between O(log n) and O(n), performing better on <a 953 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 954 * streams. 955 * 956 * @see LongStream#findFirst() 957 * @throws NullPointerException if the last element of the stream is null 958 */ 959 public static OptionalLong findLast(LongStream stream) { 960 // findLast(Stream) does some allocation, so we might as well box some more 961 java.util.Optional<Long> boxedLast = findLast(stream.boxed()); 962 return boxedLast.map(OptionalLong::of).orElse(OptionalLong.empty()); 963 } 964 965 /** 966 * Returns the last element of the specified stream, or {@link OptionalDouble#empty} if the stream 967 * is empty. 968 * 969 * <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This 970 * method's runtime will be between O(log n) and O(n), performing better on <a 971 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 972 * streams. 973 * 974 * @see DoubleStream#findFirst() 975 * @throws NullPointerException if the last element of the stream is null 976 */ 977 public static OptionalDouble findLast(DoubleStream stream) { 978 // findLast(Stream) does some allocation, so we might as well box some more 979 java.util.Optional<Double> boxedLast = findLast(stream.boxed()); 980 return boxedLast.map(OptionalDouble::of).orElse(OptionalDouble.empty()); 981 } 982 983 private Streams() {} 984}