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 javax.annotation.Nullable; 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).onClose(stream::close); 373 } 374 class Splitr extends MapWithIndexSpliterator<Spliterator<T>, R, Splitr> implements Consumer<T> { 375 T holder; 376 377 Splitr(Spliterator<T> splitr, long index) { 378 super(splitr, index); 379 } 380 381 @Override 382 public void accept(@Nullable T t) { 383 this.holder = t; 384 } 385 386 @Override 387 public boolean tryAdvance(Consumer<? super R> action) { 388 if (fromSpliterator.tryAdvance(this)) { 389 try { 390 action.accept(function.apply(holder, index++)); 391 return true; 392 } finally { 393 holder = null; 394 } 395 } 396 return false; 397 } 398 399 @Override 400 Splitr createSplit(Spliterator<T> from, long i) { 401 return new Splitr(from, i); 402 } 403 } 404 return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close); 405 } 406 407 /** 408 * An analogue of {@link java.util.function.Function} also accepting an index. 409 * 410 * <p>This interface is only intended for use by callers of {@link #mapWithIndex(Stream, 411 * FunctionWithIndex)}. 412 * 413 * @since 21.0 414 */ 415 @Beta 416 public interface FunctionWithIndex<T, R> { 417 /** Applies this function to the given argument and its index within a stream. */ 418 R apply(T from, long index); 419 } 420 421 private abstract static class MapWithIndexSpliterator< 422 F extends Spliterator<?>, R, S extends MapWithIndexSpliterator<F, R, S>> 423 implements Spliterator<R> { 424 final F fromSpliterator; 425 long index; 426 427 MapWithIndexSpliterator(F fromSpliterator, long index) { 428 this.fromSpliterator = fromSpliterator; 429 this.index = index; 430 } 431 432 abstract S createSplit(F from, long i); 433 434 @Override 435 public S trySplit() { 436 @SuppressWarnings("unchecked") 437 F split = (F) fromSpliterator.trySplit(); 438 if (split == null) { 439 return null; 440 } 441 S result = createSplit(split, index); 442 this.index += split.getExactSizeIfKnown(); 443 return result; 444 } 445 446 @Override 447 public long estimateSize() { 448 return fromSpliterator.estimateSize(); 449 } 450 451 @Override 452 public int characteristics() { 453 return fromSpliterator.characteristics() 454 & (Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED); 455 } 456 } 457 458 /** 459 * Returns a stream consisting of the results of applying the given function to the elements of 460 * {@code stream} and their indexes in the stream. For example, 461 * 462 * <pre>{@code 463 * mapWithIndex( 464 * IntStream.of(0, 1, 2), 465 * (i, index) -> i + ":" + index) 466 * }</pre> 467 * 468 * <p>...would return {@code Stream.of("0:0", "1:1", "2:2")}. 469 * 470 * <p>The resulting stream is <a 471 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 472 * if and only if {@code stream} was efficiently splittable and its underlying spliterator 473 * reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream 474 * comes from a data structure supporting efficient indexed random access, typically an array or 475 * list. 476 * 477 * <p>The order of the resulting stream is defined if and only if the order of the original stream 478 * was defined. 479 */ 480 public static <R> Stream<R> mapWithIndex(IntStream stream, IntFunctionWithIndex<R> function) { 481 checkNotNull(stream); 482 checkNotNull(function); 483 boolean isParallel = stream.isParallel(); 484 Spliterator.OfInt fromSpliterator = stream.spliterator(); 485 486 if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 487 PrimitiveIterator.OfInt fromIterator = Spliterators.iterator(fromSpliterator); 488 return StreamSupport.stream( 489 new AbstractSpliterator<R>( 490 fromSpliterator.estimateSize(), 491 fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) { 492 long index = 0; 493 494 @Override 495 public boolean tryAdvance(Consumer<? super R> action) { 496 if (fromIterator.hasNext()) { 497 action.accept(function.apply(fromIterator.nextInt(), index++)); 498 return true; 499 } 500 return false; 501 } 502 }, 503 isParallel) 504 .onClose(stream::close); 505 } 506 class Splitr extends MapWithIndexSpliterator<Spliterator.OfInt, R, Splitr> 507 implements IntConsumer, Spliterator<R> { 508 int holder; 509 510 Splitr(Spliterator.OfInt splitr, long index) { 511 super(splitr, index); 512 } 513 514 @Override 515 public void accept(int t) { 516 this.holder = t; 517 } 518 519 @Override 520 public boolean tryAdvance(Consumer<? super R> action) { 521 if (fromSpliterator.tryAdvance(this)) { 522 action.accept(function.apply(holder, index++)); 523 return true; 524 } 525 return false; 526 } 527 528 @Override 529 Splitr createSplit(Spliterator.OfInt from, long i) { 530 return new Splitr(from, i); 531 } 532 } 533 return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close); 534 } 535 536 /** 537 * An analogue of {@link java.util.function.IntFunction} also accepting an index. 538 * 539 * <p>This interface is only intended for use by callers of {@link #mapWithIndex(IntStream, 540 * IntFunctionWithIndex)}. 541 * 542 * @since 21.0 543 */ 544 @Beta 545 public interface IntFunctionWithIndex<R> { 546 /** Applies this function to the given argument and its index within a stream. */ 547 R apply(int from, long index); 548 } 549 550 /** 551 * Returns a stream consisting of the results of applying the given function to the elements of 552 * {@code stream} and their indexes in the stream. For example, 553 * 554 * <pre>{@code 555 * mapWithIndex( 556 * LongStream.of(0, 1, 2), 557 * (i, index) -> i + ":" + index) 558 * }</pre> 559 * 560 * <p>...would return {@code Stream.of("0:0", "1:1", "2:2")}. 561 * 562 * <p>The resulting stream is <a 563 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 564 * if and only if {@code stream} was efficiently splittable and its underlying spliterator 565 * reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream 566 * comes from a data structure supporting efficient indexed random access, typically an array or 567 * list. 568 * 569 * <p>The order of the resulting stream is defined if and only if the order of the original stream 570 * was defined. 571 */ 572 public static <R> Stream<R> mapWithIndex(LongStream stream, LongFunctionWithIndex<R> function) { 573 checkNotNull(stream); 574 checkNotNull(function); 575 boolean isParallel = stream.isParallel(); 576 Spliterator.OfLong fromSpliterator = stream.spliterator(); 577 578 if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 579 PrimitiveIterator.OfLong fromIterator = Spliterators.iterator(fromSpliterator); 580 return StreamSupport.stream( 581 new AbstractSpliterator<R>( 582 fromSpliterator.estimateSize(), 583 fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) { 584 long index = 0; 585 586 @Override 587 public boolean tryAdvance(Consumer<? super R> action) { 588 if (fromIterator.hasNext()) { 589 action.accept(function.apply(fromIterator.nextLong(), index++)); 590 return true; 591 } 592 return false; 593 } 594 }, 595 isParallel) 596 .onClose(stream::close); 597 } 598 class Splitr extends MapWithIndexSpliterator<Spliterator.OfLong, R, Splitr> 599 implements LongConsumer, Spliterator<R> { 600 long holder; 601 602 Splitr(Spliterator.OfLong splitr, long index) { 603 super(splitr, index); 604 } 605 606 @Override 607 public void accept(long t) { 608 this.holder = t; 609 } 610 611 @Override 612 public boolean tryAdvance(Consumer<? super R> action) { 613 if (fromSpliterator.tryAdvance(this)) { 614 action.accept(function.apply(holder, index++)); 615 return true; 616 } 617 return false; 618 } 619 620 @Override 621 Splitr createSplit(Spliterator.OfLong from, long i) { 622 return new Splitr(from, i); 623 } 624 } 625 return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close); 626 } 627 628 /** 629 * An analogue of {@link java.util.function.LongFunction} also accepting an index. 630 * 631 * <p>This interface is only intended for use by callers of {@link #mapWithIndex(LongStream, 632 * LongFunctionWithIndex)}. 633 * 634 * @since 21.0 635 */ 636 @Beta 637 public interface LongFunctionWithIndex<R> { 638 /** Applies this function to the given argument and its index within a stream. */ 639 R apply(long from, long index); 640 } 641 642 /** 643 * Returns a stream consisting of the results of applying the given function to the elements of 644 * {@code stream} and their indexes in the stream. For example, 645 * 646 * <pre>{@code 647 * mapWithIndex( 648 * DoubleStream.of(0, 1, 2), 649 * (x, index) -> x + ":" + index) 650 * }</pre> 651 * 652 * <p>...would return {@code Stream.of("0.0:0", "1.0:1", "2.0:2")}. 653 * 654 * <p>The resulting stream is <a 655 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 656 * if and only if {@code stream} was efficiently splittable and its underlying spliterator 657 * reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream 658 * comes from a data structure supporting efficient indexed random access, typically an array or 659 * list. 660 * 661 * <p>The order of the resulting stream is defined if and only if the order of the original stream 662 * was defined. 663 */ 664 public static <R> Stream<R> mapWithIndex( 665 DoubleStream stream, DoubleFunctionWithIndex<R> function) { 666 checkNotNull(stream); 667 checkNotNull(function); 668 boolean isParallel = stream.isParallel(); 669 Spliterator.OfDouble fromSpliterator = stream.spliterator(); 670 671 if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 672 PrimitiveIterator.OfDouble fromIterator = Spliterators.iterator(fromSpliterator); 673 return StreamSupport.stream( 674 new AbstractSpliterator<R>( 675 fromSpliterator.estimateSize(), 676 fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) { 677 long index = 0; 678 679 @Override 680 public boolean tryAdvance(Consumer<? super R> action) { 681 if (fromIterator.hasNext()) { 682 action.accept(function.apply(fromIterator.nextDouble(), index++)); 683 return true; 684 } 685 return false; 686 } 687 }, 688 isParallel) 689 .onClose(stream::close); 690 } 691 class Splitr extends MapWithIndexSpliterator<Spliterator.OfDouble, R, Splitr> 692 implements DoubleConsumer, Spliterator<R> { 693 double holder; 694 695 Splitr(Spliterator.OfDouble splitr, long index) { 696 super(splitr, index); 697 } 698 699 @Override 700 public void accept(double t) { 701 this.holder = t; 702 } 703 704 @Override 705 public boolean tryAdvance(Consumer<? super R> action) { 706 if (fromSpliterator.tryAdvance(this)) { 707 action.accept(function.apply(holder, index++)); 708 return true; 709 } 710 return false; 711 } 712 713 @Override 714 Splitr createSplit(Spliterator.OfDouble from, long i) { 715 return new Splitr(from, i); 716 } 717 } 718 return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close); 719 } 720 721 /** 722 * An analogue of {@link java.util.function.DoubleFunction} also accepting an index. 723 * 724 * <p>This interface is only intended for use by callers of {@link #mapWithIndex(DoubleStream, 725 * DoubleFunctionWithIndex)}. 726 * 727 * @since 21.0 728 */ 729 @Beta 730 public interface DoubleFunctionWithIndex<R> { 731 /** Applies this function to the given argument and its index within a stream. */ 732 R apply(double from, long index); 733 } 734 735 /** 736 * Returns the last element of the specified stream, or {@link java.util.Optional#empty} if the 737 * stream is empty. 738 * 739 * <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This 740 * method's runtime will be between O(log n) and O(n), performing better on <a 741 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 742 * streams. 743 * 744 * <p>If the stream has nondeterministic order, this has equivalent semantics to {@link 745 * Stream#findAny} (which you might as well use). 746 * 747 * @see Stream#findFirst() 748 * @throws NullPointerException if the last element of the stream is null 749 */ 750 public static <T> java.util.Optional<T> findLast(Stream<T> stream) { 751 class OptionalState { 752 boolean set = false; 753 T value = null; 754 755 void set(@Nullable T value) { 756 this.set = true; 757 this.value = value; 758 } 759 760 T get() { 761 checkState(set); 762 return value; 763 } 764 } 765 OptionalState state = new OptionalState(); 766 767 Deque<Spliterator<T>> splits = new ArrayDeque<>(); 768 splits.addLast(stream.spliterator()); 769 770 while (!splits.isEmpty()) { 771 Spliterator<T> spliterator = splits.removeLast(); 772 773 if (spliterator.getExactSizeIfKnown() == 0) { 774 continue; // drop this split 775 } 776 777 // Many spliterators will have trySplits that are SUBSIZED even if they are not themselves 778 // SUBSIZED. 779 if (spliterator.hasCharacteristics(Spliterator.SUBSIZED)) { 780 // we can drill down to exactly the smallest nonempty spliterator 781 while (true) { 782 Spliterator<T> prefix = spliterator.trySplit(); 783 if (prefix == null || prefix.getExactSizeIfKnown() == 0) { 784 break; 785 } else if (spliterator.getExactSizeIfKnown() == 0) { 786 spliterator = prefix; 787 break; 788 } 789 } 790 791 // spliterator is known to be nonempty now 792 spliterator.forEachRemaining(state::set); 793 return java.util.Optional.of(state.get()); 794 } 795 796 Spliterator<T> prefix = spliterator.trySplit(); 797 if (prefix == null || prefix.getExactSizeIfKnown() == 0) { 798 // we can't split this any further 799 spliterator.forEachRemaining(state::set); 800 if (state.set) { 801 return java.util.Optional.of(state.get()); 802 } 803 // fall back to the last split 804 continue; 805 } 806 splits.addLast(prefix); 807 splits.addLast(spliterator); 808 } 809 return java.util.Optional.empty(); 810 } 811 812 /** 813 * Returns the last element of the specified stream, or {@link OptionalInt#empty} if the stream is 814 * empty. 815 * 816 * <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This 817 * method's runtime will be between O(log n) and O(n), performing better on <a 818 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 819 * streams. 820 * 821 * @see IntStream#findFirst() 822 * @throws NullPointerException if the last element of the stream is null 823 */ 824 public static OptionalInt findLast(IntStream stream) { 825 // findLast(Stream) does some allocation, so we might as well box some more 826 java.util.Optional<Integer> boxedLast = findLast(stream.boxed()); 827 return boxedLast.isPresent() ? OptionalInt.of(boxedLast.get()) : OptionalInt.empty(); 828 } 829 830 /** 831 * Returns the last element of the specified stream, or {@link OptionalLong#empty} if the stream 832 * is empty. 833 * 834 * <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This 835 * method's runtime will be between O(log n) and O(n), performing better on <a 836 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 837 * streams. 838 * 839 * @see LongStream#findFirst() 840 * @throws NullPointerException if the last element of the stream is null 841 */ 842 public static OptionalLong findLast(LongStream stream) { 843 // findLast(Stream) does some allocation, so we might as well box some more 844 java.util.Optional<Long> boxedLast = findLast(stream.boxed()); 845 return boxedLast.isPresent() ? OptionalLong.of(boxedLast.get()) : OptionalLong.empty(); 846 } 847 848 /** 849 * Returns the last element of the specified stream, or {@link OptionalDouble#empty} if the stream 850 * is empty. 851 * 852 * <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This 853 * method's runtime will be between O(log n) and O(n), performing better on <a 854 * href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a> 855 * streams. 856 * 857 * @see DoubleStream#findFirst() 858 * @throws NullPointerException if the last element of the stream is null 859 */ 860 public static OptionalDouble findLast(DoubleStream stream) { 861 // findLast(Stream) does some allocation, so we might as well box some more 862 java.util.Optional<Double> boxedLast = findLast(stream.boxed()); 863 return boxedLast.isPresent() ? OptionalDouble.of(boxedLast.get()) : OptionalDouble.empty(); 864 } 865 866 private Streams() {} 867}