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