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