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