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}