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