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