Coverage Summary for Class: CollectSpliterators (com.google.common.collect)
| Class | Method, % | Line, % |
|---|---|---|
| CollectSpliterators | 0% (0/9) | 0% (0/31) |
| CollectSpliterators$1 | 0% (0/7) | 0% (0/8) |
| CollectSpliterators$1Splitr | 0% (0/7) | 0% (0/15) |
| CollectSpliterators$1WithCharacteristics | 0% (0/7) | 0% (0/11) |
| CollectSpliterators$FlatMapSpliterator | 0% (0/8) | 0% (0/43) |
| CollectSpliterators$FlatMapSpliteratorOfDouble | 0% (0/1) | 0% (0/1) |
| CollectSpliterators$FlatMapSpliteratorOfInt | 0% (0/1) | 0% (0/1) |
| CollectSpliterators$FlatMapSpliteratorOfLong | 0% (0/1) | 0% (0/1) |
| CollectSpliterators$FlatMapSpliteratorOfObject | 0% (0/1) | 0% (0/1) |
| CollectSpliterators$FlatMapSpliteratorOfPrimitive | 0% (0/5) | 0% (0/16) |
| Total | 0% (0/47) | 0% (0/128) |
1 /* 2 * Copyright (C) 2015 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may 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 implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.collect; 18 19 import static com.google.common.base.Preconditions.checkArgument; 20 import static com.google.common.base.Preconditions.checkNotNull; 21 22 import com.google.common.annotations.GwtCompatible; 23 import com.google.j2objc.annotations.Weak; 24 import java.util.Comparator; 25 import java.util.Spliterator; 26 import java.util.function.Consumer; 27 import java.util.function.DoubleConsumer; 28 import java.util.function.Function; 29 import java.util.function.IntConsumer; 30 import java.util.function.IntFunction; 31 import java.util.function.LongConsumer; 32 import java.util.function.Predicate; 33 import java.util.stream.IntStream; 34 import org.checkerframework.checker.nullness.qual.Nullable; 35 36 /** Spliterator utilities for {@code common.collect} internals. */ 37 @GwtCompatible 38 final class CollectSpliterators { 39 private CollectSpliterators() {} 40 41 static <T> Spliterator<T> indexed(int size, int extraCharacteristics, IntFunction<T> function) { 42 return indexed(size, extraCharacteristics, function, null); 43 } 44 45 static <T> Spliterator<T> indexed( 46 int size, 47 int extraCharacteristics, 48 IntFunction<T> function, 49 Comparator<? super T> comparator) { 50 if (comparator != null) { 51 checkArgument((extraCharacteristics & Spliterator.SORTED) != 0); 52 } 53 class WithCharacteristics implements Spliterator<T> { 54 private final Spliterator.OfInt delegate; 55 56 WithCharacteristics(Spliterator.OfInt delegate) { 57 this.delegate = delegate; 58 } 59 60 @Override 61 public boolean tryAdvance(Consumer<? super T> action) { 62 return delegate.tryAdvance((IntConsumer) i -> action.accept(function.apply(i))); 63 } 64 65 @Override 66 public void forEachRemaining(Consumer<? super T> action) { 67 delegate.forEachRemaining((IntConsumer) i -> action.accept(function.apply(i))); 68 } 69 70 @Override 71 public @Nullable Spliterator<T> trySplit() { 72 Spliterator.OfInt split = delegate.trySplit(); 73 return (split == null) ? null : new WithCharacteristics(split); 74 } 75 76 @Override 77 public long estimateSize() { 78 return delegate.estimateSize(); 79 } 80 81 @Override 82 public int characteristics() { 83 return Spliterator.ORDERED 84 | Spliterator.SIZED 85 | Spliterator.SUBSIZED 86 | extraCharacteristics; 87 } 88 89 @Override 90 public Comparator<? super T> getComparator() { 91 if (hasCharacteristics(Spliterator.SORTED)) { 92 return comparator; 93 } else { 94 throw new IllegalStateException(); 95 } 96 } 97 } 98 return new WithCharacteristics(IntStream.range(0, size).spliterator()); 99 } 100 101 /** 102 * Returns a {@code Spliterator} over the elements of {@code fromSpliterator} mapped by {@code 103 * function}. 104 */ 105 static <InElementT, OutElementT> Spliterator<OutElementT> map( 106 Spliterator<InElementT> fromSpliterator, 107 Function<? super InElementT, ? extends OutElementT> function) { 108 checkNotNull(fromSpliterator); 109 checkNotNull(function); 110 return new Spliterator<OutElementT>() { 111 112 @Override 113 public boolean tryAdvance(Consumer<? super OutElementT> action) { 114 return fromSpliterator.tryAdvance( 115 fromElement -> action.accept(function.apply(fromElement))); 116 } 117 118 @Override 119 public void forEachRemaining(Consumer<? super OutElementT> action) { 120 fromSpliterator.forEachRemaining(fromElement -> action.accept(function.apply(fromElement))); 121 } 122 123 @Override 124 public Spliterator<OutElementT> trySplit() { 125 Spliterator<InElementT> fromSplit = fromSpliterator.trySplit(); 126 return (fromSplit != null) ? map(fromSplit, function) : null; 127 } 128 129 @Override 130 public long estimateSize() { 131 return fromSpliterator.estimateSize(); 132 } 133 134 @Override 135 public int characteristics() { 136 return fromSpliterator.characteristics() 137 & ~(Spliterator.DISTINCT | Spliterator.NONNULL | Spliterator.SORTED); 138 } 139 }; 140 } 141 142 /** Returns a {@code Spliterator} filtered by the specified predicate. */ 143 static <T> Spliterator<T> filter(Spliterator<T> fromSpliterator, Predicate<? super T> predicate) { 144 checkNotNull(fromSpliterator); 145 checkNotNull(predicate); 146 class Splitr implements Spliterator<T>, Consumer<T> { 147 T holder = null; 148 149 @Override 150 public void accept(T t) { 151 this.holder = t; 152 } 153 154 @Override 155 public boolean tryAdvance(Consumer<? super T> action) { 156 while (fromSpliterator.tryAdvance(this)) { 157 try { 158 if (predicate.test(holder)) { 159 action.accept(holder); 160 return true; 161 } 162 } finally { 163 holder = null; 164 } 165 } 166 return false; 167 } 168 169 @Override 170 public Spliterator<T> trySplit() { 171 Spliterator<T> fromSplit = fromSpliterator.trySplit(); 172 return (fromSplit == null) ? null : filter(fromSplit, predicate); 173 } 174 175 @Override 176 public long estimateSize() { 177 return fromSpliterator.estimateSize() / 2; 178 } 179 180 @Override 181 public Comparator<? super T> getComparator() { 182 return fromSpliterator.getComparator(); 183 } 184 185 @Override 186 public int characteristics() { 187 return fromSpliterator.characteristics() 188 & (Spliterator.DISTINCT 189 | Spliterator.NONNULL 190 | Spliterator.ORDERED 191 | Spliterator.SORTED); 192 } 193 } 194 return new Splitr(); 195 } 196 197 /** 198 * Returns a {@code Spliterator} that iterates over the elements of the spliterators generated by 199 * applying {@code function} to the elements of {@code fromSpliterator}. 200 */ 201 static <InElementT, OutElementT> Spliterator<OutElementT> flatMap( 202 Spliterator<InElementT> fromSpliterator, 203 Function<? super InElementT, Spliterator<OutElementT>> function, 204 int topCharacteristics, 205 long topSize) { 206 checkArgument( 207 (topCharacteristics & Spliterator.SUBSIZED) == 0, 208 "flatMap does not support SUBSIZED characteristic"); 209 checkArgument( 210 (topCharacteristics & Spliterator.SORTED) == 0, 211 "flatMap does not support SORTED characteristic"); 212 checkNotNull(fromSpliterator); 213 checkNotNull(function); 214 return new FlatMapSpliteratorOfObject<InElementT, OutElementT>( 215 null, fromSpliterator, function, topCharacteristics, topSize); 216 } 217 218 /** 219 * Returns a {@code Spliterator.OfInt} that iterates over the elements of the spliterators 220 * generated by applying {@code function} to the elements of {@code fromSpliterator}. (If {@code 221 * function} returns {@code null} for an input, it is replaced with an empty stream.) 222 */ 223 static <InElementT> Spliterator.OfInt flatMapToInt( 224 Spliterator<InElementT> fromSpliterator, 225 Function<? super InElementT, Spliterator.OfInt> function, 226 int topCharacteristics, 227 long topSize) { 228 checkArgument( 229 (topCharacteristics & Spliterator.SUBSIZED) == 0, 230 "flatMap does not support SUBSIZED characteristic"); 231 checkArgument( 232 (topCharacteristics & Spliterator.SORTED) == 0, 233 "flatMap does not support SORTED characteristic"); 234 checkNotNull(fromSpliterator); 235 checkNotNull(function); 236 return new FlatMapSpliteratorOfInt<InElementT>( 237 null, fromSpliterator, function, topCharacteristics, topSize); 238 } 239 240 /** 241 * Returns a {@code Spliterator.OfLong} that iterates over the elements of the spliterators 242 * generated by applying {@code function} to the elements of {@code fromSpliterator}. (If {@code 243 * function} returns {@code null} for an input, it is replaced with an empty stream.) 244 */ 245 static <InElementT> Spliterator.OfLong flatMapToLong( 246 Spliterator<InElementT> fromSpliterator, 247 Function<? super InElementT, Spliterator.OfLong> function, 248 int topCharacteristics, 249 long topSize) { 250 checkArgument( 251 (topCharacteristics & Spliterator.SUBSIZED) == 0, 252 "flatMap does not support SUBSIZED characteristic"); 253 checkArgument( 254 (topCharacteristics & Spliterator.SORTED) == 0, 255 "flatMap does not support SORTED characteristic"); 256 checkNotNull(fromSpliterator); 257 checkNotNull(function); 258 return new FlatMapSpliteratorOfLong<InElementT>( 259 null, fromSpliterator, function, topCharacteristics, topSize); 260 } 261 262 /** 263 * Returns a {@code Spliterator.OfDouble} that iterates over the elements of the spliterators 264 * generated by applying {@code function} to the elements of {@code fromSpliterator}. (If {@code 265 * function} returns {@code null} for an input, it is replaced with an empty stream.) 266 */ 267 static <InElementT> Spliterator.OfDouble flatMapToDouble( 268 Spliterator<InElementT> fromSpliterator, 269 Function<? super InElementT, Spliterator.OfDouble> function, 270 int topCharacteristics, 271 long topSize) { 272 checkArgument( 273 (topCharacteristics & Spliterator.SUBSIZED) == 0, 274 "flatMap does not support SUBSIZED characteristic"); 275 checkArgument( 276 (topCharacteristics & Spliterator.SORTED) == 0, 277 "flatMap does not support SORTED characteristic"); 278 checkNotNull(fromSpliterator); 279 checkNotNull(function); 280 return new FlatMapSpliteratorOfDouble<InElementT>( 281 null, fromSpliterator, function, topCharacteristics, topSize); 282 } 283 284 /** 285 * Implements the {@link Stream#flatMap} operation on spliterators. 286 * 287 * @param <InElementT> the element type of the input spliterator 288 * @param <OutElementT> the element type of the output spliterators 289 * @param <OutSpliteratorT> the type of the output spliterators 290 */ 291 abstract static class FlatMapSpliterator< 292 InElementT, OutElementT, OutSpliteratorT extends Spliterator<OutElementT>> 293 implements Spliterator<OutElementT> { 294 /** Factory for constructing {@link FlatMapSpliterator} instances. */ 295 @FunctionalInterface 296 interface Factory<InElementT, OutSpliteratorT extends Spliterator<?>> { 297 OutSpliteratorT newFlatMapSpliterator( 298 OutSpliteratorT prefix, 299 Spliterator<InElementT> fromSplit, 300 Function<? super InElementT, OutSpliteratorT> function, 301 int splitCharacteristics, 302 long estSplitSize); 303 } 304 305 @Nullable @Weak OutSpliteratorT prefix; 306 final Spliterator<InElementT> from; 307 final Function<? super InElementT, OutSpliteratorT> function; 308 final Factory<InElementT, OutSpliteratorT> factory; 309 int characteristics; 310 long estimatedSize; 311 312 FlatMapSpliterator( 313 OutSpliteratorT prefix, 314 Spliterator<InElementT> from, 315 Function<? super InElementT, OutSpliteratorT> function, 316 Factory<InElementT, OutSpliteratorT> factory, 317 int characteristics, 318 long estimatedSize) { 319 this.prefix = prefix; 320 this.from = from; 321 this.function = function; 322 this.factory = factory; 323 this.characteristics = characteristics; 324 this.estimatedSize = estimatedSize; 325 } 326 327 /* 328 * The tryAdvance and forEachRemaining in FlatMapSpliteratorOfPrimitive are overloads of these 329 * methods, not overrides. They are annotated @Override because they implement methods from 330 * Spliterator.OfPrimitive (and override default implementations from Spliterator.OfPrimitive or 331 * a subtype like Spliterator.OfInt). 332 */ 333 334 @Override 335 public final boolean tryAdvance(Consumer<? super OutElementT> action) { 336 while (true) { 337 if (prefix != null && prefix.tryAdvance(action)) { 338 if (estimatedSize != Long.MAX_VALUE) { 339 estimatedSize--; 340 } 341 return true; 342 } else { 343 prefix = null; 344 } 345 if (!from.tryAdvance(fromElement -> prefix = function.apply(fromElement))) { 346 return false; 347 } 348 } 349 } 350 351 @Override 352 public final void forEachRemaining(Consumer<? super OutElementT> action) { 353 if (prefix != null) { 354 prefix.forEachRemaining(action); 355 prefix = null; 356 } 357 from.forEachRemaining( 358 fromElement -> { 359 Spliterator<OutElementT> elements = function.apply(fromElement); 360 if (elements != null) { 361 elements.forEachRemaining(action); 362 } 363 }); 364 estimatedSize = 0; 365 } 366 367 @Override 368 public final OutSpliteratorT trySplit() { 369 Spliterator<InElementT> fromSplit = from.trySplit(); 370 if (fromSplit != null) { 371 int splitCharacteristics = characteristics & ~Spliterator.SIZED; 372 long estSplitSize = estimateSize(); 373 if (estSplitSize < Long.MAX_VALUE) { 374 estSplitSize /= 2; 375 this.estimatedSize -= estSplitSize; 376 this.characteristics = splitCharacteristics; 377 } 378 OutSpliteratorT result = 379 factory.newFlatMapSpliterator( 380 this.prefix, fromSplit, function, splitCharacteristics, estSplitSize); 381 this.prefix = null; 382 return result; 383 } else if (prefix != null) { 384 OutSpliteratorT result = prefix; 385 this.prefix = null; 386 return result; 387 } else { 388 return null; 389 } 390 } 391 392 @Override 393 public final long estimateSize() { 394 if (prefix != null) { 395 estimatedSize = Math.max(estimatedSize, prefix.estimateSize()); 396 } 397 return Math.max(estimatedSize, 0); 398 } 399 400 @Override 401 public final int characteristics() { 402 return characteristics; 403 } 404 } 405 406 /** 407 * Implementation of {@link Stream#flatMap} with an object spliterator output type. 408 * 409 * <p>To avoid having this type, we could use {@code FlatMapSpliterator} directly. The main 410 * advantages to having the type are the ability to use its constructor reference below and the 411 * parallelism with the primitive version. In short, it makes its caller ({@code flatMap}) 412 * simpler. 413 * 414 * @param <InElementT> the element type of the input spliterator 415 * @param <OutElementT> the element type of the output spliterators 416 */ 417 static final class FlatMapSpliteratorOfObject<InElementT, OutElementT> 418 extends FlatMapSpliterator<InElementT, OutElementT, Spliterator<OutElementT>> { 419 FlatMapSpliteratorOfObject( 420 Spliterator<OutElementT> prefix, 421 Spliterator<InElementT> from, 422 Function<? super InElementT, Spliterator<OutElementT>> function, 423 int characteristics, 424 long estimatedSize) { 425 super( 426 prefix, from, function, FlatMapSpliteratorOfObject::new, characteristics, estimatedSize); 427 } 428 } 429 430 /** 431 * Implementation of {@link Stream#flatMap} with a primitive spliterator output type. 432 * 433 * @param <InElementT> the element type of the input spliterator 434 * @param <OutElementT> the (boxed) element type of the output spliterators 435 * @param <OutConsumerT> the specialized consumer type for the primitive output type 436 * @param <OutSpliteratorT> the primitive spliterator type associated with {@code OutElementT} 437 */ 438 abstract static class FlatMapSpliteratorOfPrimitive< 439 InElementT, 440 OutElementT, 441 OutConsumerT, 442 OutSpliteratorT extends 443 Spliterator.OfPrimitive<OutElementT, OutConsumerT, OutSpliteratorT>> 444 extends FlatMapSpliterator<InElementT, OutElementT, OutSpliteratorT> 445 implements Spliterator.OfPrimitive<OutElementT, OutConsumerT, OutSpliteratorT> { 446 447 FlatMapSpliteratorOfPrimitive( 448 OutSpliteratorT prefix, 449 Spliterator<InElementT> from, 450 Function<? super InElementT, OutSpliteratorT> function, 451 Factory<InElementT, OutSpliteratorT> factory, 452 int characteristics, 453 long estimatedSize) { 454 super(prefix, from, function, factory, characteristics, estimatedSize); 455 } 456 457 @Override 458 public final boolean tryAdvance(OutConsumerT action) { 459 while (true) { 460 if (prefix != null && prefix.tryAdvance(action)) { 461 if (estimatedSize != Long.MAX_VALUE) { 462 estimatedSize--; 463 } 464 return true; 465 } else { 466 prefix = null; 467 } 468 if (!from.tryAdvance(fromElement -> prefix = function.apply(fromElement))) { 469 return false; 470 } 471 } 472 } 473 474 @Override 475 public final void forEachRemaining(OutConsumerT action) { 476 if (prefix != null) { 477 prefix.forEachRemaining(action); 478 prefix = null; 479 } 480 from.forEachRemaining( 481 fromElement -> { 482 OutSpliteratorT elements = function.apply(fromElement); 483 if (elements != null) { 484 elements.forEachRemaining(action); 485 } 486 }); 487 estimatedSize = 0; 488 } 489 } 490 491 /** Implementation of {@link #flatMapToInt}. */ 492 static final class FlatMapSpliteratorOfInt<InElementT> 493 extends FlatMapSpliteratorOfPrimitive<InElementT, Integer, IntConsumer, Spliterator.OfInt> 494 implements Spliterator.OfInt { 495 FlatMapSpliteratorOfInt( 496 Spliterator.OfInt prefix, 497 Spliterator<InElementT> from, 498 Function<? super InElementT, Spliterator.OfInt> function, 499 int characteristics, 500 long estimatedSize) { 501 super(prefix, from, function, FlatMapSpliteratorOfInt::new, characteristics, estimatedSize); 502 } 503 } 504 505 /** Implementation of {@link #flatMapToLong}. */ 506 static final class FlatMapSpliteratorOfLong<InElementT> 507 extends FlatMapSpliteratorOfPrimitive<InElementT, Long, LongConsumer, Spliterator.OfLong> 508 implements Spliterator.OfLong { 509 FlatMapSpliteratorOfLong( 510 Spliterator.OfLong prefix, 511 Spliterator<InElementT> from, 512 Function<? super InElementT, Spliterator.OfLong> function, 513 int characteristics, 514 long estimatedSize) { 515 super(prefix, from, function, FlatMapSpliteratorOfLong::new, characteristics, estimatedSize); 516 } 517 } 518 519 /** Implementation of {@link #flatMapToDouble}. */ 520 static final class FlatMapSpliteratorOfDouble<InElementT> 521 extends FlatMapSpliteratorOfPrimitive< 522 InElementT, Double, DoubleConsumer, Spliterator.OfDouble> 523 implements Spliterator.OfDouble { 524 FlatMapSpliteratorOfDouble( 525 Spliterator.OfDouble prefix, 526 Spliterator<InElementT> from, 527 Function<? super InElementT, Spliterator.OfDouble> function, 528 int characteristics, 529 long estimatedSize) { 530 super( 531 prefix, from, function, FlatMapSpliteratorOfDouble::new, characteristics, estimatedSize); 532 } 533 } 534 }