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