Coverage Summary for Class: Streams (com.google.common.collect)

Class Method, % Line, %
Streams 0% (0/33) 0% (0/171)
Streams$1 0% (0/2) 0% (0/5)
Streams$1OptionalState 0% (0/3) 0% (0/7)
Streams$1Splitr 0% (0/4) 0% (0/10)
Streams$2 0% (0/2) 0% (0/6)
Streams$2Splitr 0% (0/4) 0% (0/8)
Streams$3 0% (0/2) 0% (0/6)
Streams$3Splitr 0% (0/4) 0% (0/8)
Streams$4 0% (0/2) 0% (0/6)
Streams$4Splitr 0% (0/4) 0% (0/8)
Streams$5 0% (0/2) 0% (0/6)
Streams$MapWithIndexSpliterator 0% (0/4) 0% (0/11)
Streams$TemporaryPair 0% (0/1) 0% (0/3)
Total 0% (0/67) 0% (0/255)


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