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