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