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