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