1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.util.Spliterator; 13 14 15 enum SpliteratorCharacteristic { 16 /** 17 * Characteristic value signifying that an encounter order is defined for 18 * elements. If so, this Spliterator guarantees that method 19 * {@link #trySplit} splits a strict prefix of elements, that method 20 * {@link #tryAdvance} steps by one element in prefix order, and that 21 * {@link #forEachRemaining} performs actions in encounter order. 22 * 23 * <p>A {@link Collection} has an encounter order if the corresponding 24 * {@link Collection#iterator} documents an order. If so, the encounter 25 * order is the same as the documented order. Otherwise, a collection does 26 * not have an encounter order. 27 * 28 * @apiNote Encounter order is guaranteed to be ascending index order for 29 * any {@link List}. But no order is guaranteed for hash-based collections 30 * such as {@link HashSet}. Clients of a Spliterator that reports 31 * {@code ORDERED} are expected to preserve ordering constraints in 32 * non-commutative parallel computations. 33 */ 34 ORDERED = 0x00000010, 35 36 /** 37 * Characteristic value signifying that, for each pair of 38 * encountered elements {@code x, y}, {@code !x.equals(y)}. This 39 * applies for example, to a Spliterator based on a {@link Set}. 40 */ 41 DISTINCT = 0x00000001, 42 43 /** 44 * Characteristic value signifying that encounter order follows a defined 45 * sort order. If so, method {@link #getComparator()} returns the associated 46 * Comparator, or {@code null} if all elements are {@link Comparable} and 47 * are sorted by their natural ordering. 48 * 49 * <p>A Spliterator that reports {@code SORTED} must also report 50 * {@code ORDERED}. 51 * 52 * @apiNote The spliterators for {@code Collection} classes in the JDK that 53 * implement {@link NavigableSet} or {@link SortedSet} report {@code SORTED}. 54 */ 55 SORTED = 0x00000004, 56 57 /** 58 * Characteristic value signifying that the value returned from 59 * {@code estimateSize()} prior to traversal or splitting represents a 60 * finite size that, in the absence of structural source modification, 61 * represents an exact count of the number of elements that would be 62 * encountered by a complete traversal. 63 * 64 * @apiNote Most Spliterators for Collections, that cover all elements of a 65 * {@code Collection} report this characteristic. Sub-spliterators, such as 66 * those for {@link HashSet}, that cover a sub-set of elements and 67 * approximate their reported size do not. 68 */ 69 SIZED = 0x00000040, 70 71 /** 72 * Characteristic value signifying that the source guarantees that 73 * encountered elements will not be {@code null}. (This applies, 74 * for example, to most concurrent collections, queues, and maps.) 75 */ 76 NONNULL = 0x00000100, 77 78 /** 79 * Characteristic value signifying that the element source cannot be 80 * structurally modified; that is, elements cannot be added, replaced, or 81 * removed, so such changes cannot occur during traversal. A Spliterator 82 * that does not report {@code IMMUTABLE} or {@code CONCURRENT} is expected 83 * to have a documented policy (for example throwing 84 * {@link ConcurrentModificationException}) concerning structural 85 * interference detected during traversal. 86 */ 87 IMMUTABLE = 0x00000400, 88 89 /** 90 * Characteristic value signifying that the element source may be safely 91 * concurrently modified (allowing additions, replacements, and/or removals) 92 * by multiple threads without external synchronization. If so, the 93 * Spliterator is expected to have a documented policy concerning the impact 94 * of modifications during traversal. 95 * 96 * <p>A top-level Spliterator should not report both {@code CONCURRENT} and 97 * {@code SIZED}, since the finite size, if known, may change if the source 98 * is concurrently modified during traversal. Such a Spliterator is 99 * inconsistent and no guarantees can be made about any computation using 100 * that Spliterator. Sub-spliterators may report {@code SIZED} if the 101 * sub-split size is known and additions or removals to the source are not 102 * reflected when traversing. 103 * 104 * @apiNote Most concurrent collections maintain a consistency policy 105 * guaranteeing accuracy with respect to elements present at the point of 106 * Spliterator construction, but possibly not reflecting subsequent 107 * additions or removals. 108 */ 109 CONCURRENT = 0x00001000, 110 111 /** 112 * Characteristic value signifying that all Spliterators resulting from 113 * {@code trySplit()} will be both {@link #SIZED} and {@link #SUBSIZED}. 114 * (This means that all child Spliterators, whether direct or indirect, will 115 * be {@code SIZED}.) 116 * 117 * <p>A Spliterator that does not report {@code SIZED} as required by 118 * {@code SUBSIZED} is inconsistent and no guarantees can be made about any 119 * computation using that Spliterator. 120 * 121 * @apiNote Some spliterators, such as the top-level spliterator for an 122 * approximately balanced binary tree, will report {@code SIZED} but not 123 * {@code SUBSIZED}, since it is common to know the size of the entire tree 124 * but not the exact sizes of subtrees. 125 */ 126 SUBSIZED = 0x00004000 127 } 128 129 /** 130 * An object for traversing and partitioning elements of a source. The source 131 * of elements covered by a Spliterator could be, for example, an array, a 132 * {@link Collection}, an IO channel, or a generator function. 133 * 134 * <p>A Spliterator may traverse elements individually ({@link 135 * #tryAdvance tryAdvance()}) or sequentially in bulk 136 * ({@link #forEachRemaining forEachRemaining()}). 137 * 138 * <p>A Spliterator may also partition off some of its elements (using 139 * {@link #trySplit}) as another Spliterator, to be used in 140 * possibly-parallel operations. Operations using a Spliterator that 141 * cannot split, or does so in a highly imbalanced or inefficient 142 * manner, are unlikely to benefit from parallelism. Traversal 143 * and splitting exhaust elements; each Spliterator is useful for only a single 144 * bulk computation. 145 * 146 * <p>A Spliterator also reports a set of {@link #characteristics()} of its 147 * structure, source, and elements from among {@link #ORDERED}, 148 * {@link #DISTINCT}, {@link #SORTED}, {@link #SIZED}, {@link #NONNULL}, 149 * {@link #IMMUTABLE}, {@link #CONCURRENT}, and {@link #SUBSIZED}. These may 150 * be employed by Spliterator clients to control, specialize or simplify 151 * computation. For example, a Spliterator for a {@link Collection} would 152 * report {@code SIZED}, a Spliterator for a {@link Set} would report 153 * {@code DISTINCT}, and a Spliterator for a {@link SortedSet} would also 154 * report {@code SORTED}. Characteristics are reported as a simple unioned bit 155 * set. 156 * 157 * Some characteristics additionally constrain method behavior; for example if 158 * {@code ORDERED}, traversal methods must conform to their documented ordering. 159 * New characteristics may be defined in the future, so implementors should not 160 * assign meanings to unlisted values. 161 * 162 * <p><a name="binding">A Spliterator that does not report {@code IMMUTABLE} or 163 * {@code CONCURRENT} is expected to have a documented policy concerning: 164 * when the spliterator <em>binds</em> to the element source; and detection of 165 * structural interference of the element source detected after binding.</a> A 166 * <em>late-binding</em> Spliterator binds to the source of elements at the 167 * point of first traversal, first split, or first query for estimated size, 168 * rather than at the time the Spliterator is created. A Spliterator that is 169 * not <em>late-binding</em> binds to the source of elements at the point of 170 * construction or first invocation of any method. Modifications made to the 171 * source prior to binding are reflected when the Spliterator is traversed. 172 * After binding a Spliterator should, on a best-effort basis, throw 173 * {@link ConcurrentModificationException} if structural interference is 174 * detected. Spliterators that do this are called <em>fail-fast</em>. The 175 * bulk traversal method ({@link #forEachRemaining forEachRemaining()}) of a 176 * Spliterator may optimize traversal and check for structural interference 177 * after all elements have been traversed, rather than checking per-element and 178 * failing immediately. 179 * 180 * <p>Spliterators can provide an estimate of the number of remaining elements 181 * via the {@link #estimateSize} method. Ideally, as reflected in characteristic 182 * {@link #SIZED}, this value corresponds exactly to the number of elements 183 * that would be encountered in a successful traversal. However, even when not 184 * exactly known, an estimated value value may still be useful to operations 185 * being performed on the source, such as helping to determine whether it is 186 * preferable to split further or traverse the remaining elements sequentially. 187 * 188 * <p>Despite their obvious utility in parallel algorithms, spliterators are not 189 * expected to be thread-safe; instead, implementations of parallel algorithms 190 * using spliterators should ensure that the spliterator is only used by one 191 * thread at a time. This is generally easy to attain via <em>serial 192 * thread-confinement</em>, which often is a natural consequence of typical 193 * parallel algorithms that work by recursive decomposition. A thread calling 194 * {@link #trySplit()} may hand over the returned Spliterator to another thread, 195 * which in turn may traverse or further split that Spliterator. The behaviour 196 * of splitting and traversal is undefined if two or more threads operate 197 * concurrently on the same spliterator. If the original thread hands a 198 * spliterator off to another thread for processing, it is best if that handoff 199 * occurs before any elements are consumed with {@link #tryAdvance(Consumer) 200 * tryAdvance()}, as certain guarantees (such as the accuracy of 201 * {@link #estimateSize()} for {@code SIZED} spliterators) are only valid before 202 * traversal has begun. 203 * 204 * <p>Primitive subtype specializations of {@code Spliterator} are provided for 205 * {@link OfInt int}, {@link OfLong long}, and {@link OfDouble double} values. 206 * The subtype default implementations of 207 * {@link Spliterator#tryAdvance(hunt.util.functional.Consumer)} 208 * and {@link Spliterator#forEachRemaining(hunt.util.functional.Consumer)} box 209 * primitive values to instances of their corresponding wrapper class. Such 210 * boxing may undermine any performance advantages gained by using the primitive 211 * specializations. To avoid boxing, the corresponding primitive-based methods 212 * should be used. For example, 213 * {@link Spliterator.OfInt#tryAdvance(hunt.util.functional.IntConsumer)} 214 * and {@link Spliterator.OfInt#forEachRemaining(hunt.util.functional.IntConsumer)} 215 * should be used in preference to 216 * {@link Spliterator.OfInt#tryAdvance(hunt.util.functional.Consumer)} and 217 * {@link Spliterator.OfInt#forEachRemaining(hunt.util.functional.Consumer)}. 218 * Traversal of primitive values using boxing-based methods 219 * {@link #tryAdvance tryAdvance()} and 220 * {@link #forEachRemaining(hunt.util.functional.Consumer) forEachRemaining()} 221 * does not affect the order in which the values, transformed to boxed values, 222 * are encountered. 223 * 224 * @apiNote 225 * <p>Spliterators, like {@code Iterator}s, are for traversing the elements of 226 * a source. The {@code Spliterator} API was designed to support efficient 227 * parallel traversal in addition to sequential traversal, by supporting 228 * decomposition as well as single-element iteration. In addition, the 229 * protocol for accessing elements via a Spliterator is designed to impose 230 * smaller per-element overhead than {@code Iterator}, and to avoid the inherent 231 * race involved in having separate methods for {@code hasNext()} and 232 * {@code next()}. 233 * 234 * <p>For mutable sources, arbitrary and non-deterministic behavior may occur if 235 * the source is structurally interfered with (elements added, replaced, or 236 * removed) between the time that the Spliterator binds to its data source and 237 * the end of traversal. For example, such interference will produce arbitrary, 238 * non-deterministic results when using the {@code java.util.stream} framework. 239 * 240 * <p>Structural interference of a source can be managed in the following ways 241 * (in approximate order of decreasing desirability): 242 * <ul> 243 * <li>The source cannot be structurally interfered with. 244 * <br>For example, an instance of 245 * {@link hunt.concurrency.CopyOnWriteArrayList} is an immutable source. 246 * A Spliterator created from the source reports a characteristic of 247 * {@code IMMUTABLE}.</li> 248 * <li>The source manages concurrent modifications. 249 * <br>For example, a key set of a {@link hunt.concurrency.ConcurrentHashMap} 250 * is a concurrent source. A Spliterator created from the source reports a 251 * characteristic of {@code CONCURRENT}.</li> 252 * <li>The mutable source provides a late-binding and fail-fast Spliterator. 253 * <br>Late binding narrows the window during which interference can affect 254 * the calculation; fail-fast detects, on a best-effort basis, that structural 255 * interference has occurred after traversal has commenced and throws 256 * {@link ConcurrentModificationException}. For example, {@link ArrayList}, 257 * and many other non-concurrent {@code Collection} classes in the JDK, provide 258 * a late-binding, fail-fast spliterator.</li> 259 * <li>The mutable source provides a non-late-binding but fail-fast Spliterator. 260 * <br>The source increases the likelihood of throwing 261 * {@code ConcurrentModificationException} since the window of potential 262 * interference is larger.</li> 263 * <li>The mutable source provides a late-binding and non-fail-fast Spliterator. 264 * <br>The source risks arbitrary, non-deterministic behavior after traversal 265 * has commenced since interference is not detected. 266 * </li> 267 * <li>The mutable source provides a non-late-binding and non-fail-fast 268 * Spliterator. 269 * <br>The source increases the risk of arbitrary, non-deterministic behavior 270 * since non-detected interference may occur after construction. 271 * </li> 272 * </ul> 273 * 274 * <p><b>Example.</b> Here is a class (not a very useful one, except 275 * for illustration) that maintains an array in which the actual data 276 * are held in even locations, and unrelated tag data are held in odd 277 * locations. Its Spliterator ignores the tags. 278 * 279 * <pre> {@code 280 * class TaggedArray!(T) { 281 * private final Object[] elements; // immutable after construction 282 * TaggedArray(T[] data, Object[] tags) { 283 * int size = data.length; 284 * if (tags.length != size) throw new IllegalArgumentException(); 285 * this.elements = new Object[2 * size]; 286 * for (int i = 0, j = 0; i < size; ++i) { 287 * elements[j++] = data[i]; 288 * elements[j++] = tags[i]; 289 * } 290 * } 291 * 292 * public Spliterator!(T) spliterator() { 293 * return new TaggedArraySpliterator<>(elements, 0, elements.length); 294 * } 295 * 296 * static class TaggedArraySpliterator!(T) : Spliterator!(T) { 297 * private final Object[] array; 298 * private int origin; // current index, advanced on split or traversal 299 * private final int fence; // one past the greatest index 300 * 301 * TaggedArraySpliterator(Object[] array, int origin, int fence) { 302 * this.array = array; this.origin = origin; this.fence = fence; 303 * } 304 * 305 * public void forEachRemaining(Consumer!(T) action) { 306 * for (; origin < fence; origin += 2) 307 * action.accept((T) array[origin]); 308 * } 309 * 310 * public bool tryAdvance(Consumer!(T) action) { 311 * if (origin < fence) { 312 * action.accept((T) array[origin]); 313 * origin += 2; 314 * return true; 315 * } 316 * else // cannot advance 317 * return false; 318 * } 319 * 320 * public Spliterator!(T) trySplit() { 321 * int lo = origin; // divide range in half 322 * int mid = ((lo + fence) >>> 1) & ~1; // force midpoint to be even 323 * if (lo < mid) { // split out left half 324 * origin = mid; // reset this Spliterator's origin 325 * return new TaggedArraySpliterator<>(array, lo, mid); 326 * } 327 * else // too small to split 328 * return null; 329 * } 330 * 331 * public long estimateSize() { 332 * return (long)((fence - origin) / 2); 333 * } 334 * 335 * public int characteristics() { 336 * return ORDERED | SIZED | IMMUTABLE | SUBSIZED; 337 * } 338 * } 339 * }}</pre> 340 * 341 * <p>As an example how a parallel computation framework, such as the 342 * {@code java.util.stream} package, would use Spliterator in a parallel 343 * computation, here is one way to implement an associated parallel forEach, 344 * that illustrates the primary usage idiom of splitting off subtasks until 345 * the estimated amount of work is small enough to perform 346 * sequentially. Here we assume that the order of processing across 347 * subtasks doesn't matter; different (forked) tasks may further split 348 * and process elements concurrently in undetermined order. This 349 * example uses a {@link hunt.concurrency.CountedCompleter}; 350 * similar usages apply to other parallel task constructions. 351 * 352 * <pre>{@code 353 * static !(T) void parEach(TaggedArray!(T) a, Consumer!(T) action) { 354 * Spliterator!(T) s = a.spliterator(); 355 * long targetBatchSize = s.estimateSize() / (ForkJoinPool.getCommonPoolParallelism() * 8); 356 * new ParEach(null, s, action, targetBatchSize).invoke(); 357 * } 358 * 359 * static class ParEach!(T) extends CountedCompleter!(void) { 360 * final Spliterator!(T) spliterator; 361 * final Consumer!(T) action; 362 * final long targetBatchSize; 363 * 364 * ParEach(ParEach!(T) parent, Spliterator!(T) spliterator, 365 * Consumer!(T) action, long targetBatchSize) { 366 * super(parent); 367 * this.spliterator = spliterator; this.action = action; 368 * this.targetBatchSize = targetBatchSize; 369 * } 370 * 371 * public void compute() { 372 * Spliterator!(T) sub; 373 * while (spliterator.estimateSize() > targetBatchSize && 374 * (sub = spliterator.trySplit()) !is null) { 375 * addToPendingCount(1); 376 * new ParEach<>(this, sub, action, targetBatchSize).fork(); 377 * } 378 * spliterator.forEachRemaining(action); 379 * propagateCompletion(); 380 * } 381 * }}</pre> 382 * 383 * @implNote 384 * If the bool system property {@code org.openjdk.java.util.stream.tripwire} 385 * is set to {@code true} then diagnostic warnings are reported if boxing of 386 * primitive values occur when operating on primitive subtype specializations. 387 * 388 * @param (T) the type of elements returned by this Spliterator 389 * 390 * @see Collection 391 */ 392 interface Spliterator(T) { 393 // /** 394 // * If a remaining element exists, performs the given action on it, 395 // * returning {@code true}; else returns {@code false}. If this 396 // * Spliterator is {@link #ORDERED} the action is performed on the 397 // * next element in encounter order. Exceptions thrown by the 398 // * action are relayed to the caller. 399 // * 400 // * @param action The action 401 // * @return {@code false} if no remaining elements existed 402 // * upon entry to this method, else {@code true}. 403 // * @throws NullPointerException if the specified action is null 404 // */ 405 // bool tryAdvance(Consumer!(T) action); 406 407 // /** 408 // * Performs the given action for each remaining element, sequentially in 409 // * the current thread, until all elements have been processed or the action 410 // * throws an exception. If this Spliterator is {@link #ORDERED}, actions 411 // * are performed in encounter order. Exceptions thrown by the action 412 // * are relayed to the caller. 413 // * 414 // * @implSpec 415 // * The default implementation repeatedly invokes {@link #tryAdvance} until 416 // * it returns {@code false}. It should be overridden whenever possible. 417 // * 418 // * @param action The action 419 // * @throws NullPointerException if the specified action is null 420 // */ 421 // default void forEachRemaining(Consumer!(T) action) { 422 // do { } while (tryAdvance(action)); 423 // } 424 425 // /** 426 // * If this spliterator can be partitioned, returns a Spliterator 427 // * covering elements, that will, upon return from this method, not 428 // * be covered by this Spliterator. 429 // * 430 // * <p>If this Spliterator is {@link #ORDERED}, the returned Spliterator 431 // * must cover a strict prefix of the elements. 432 // * 433 // * <p>Unless this Spliterator covers an infinite number of elements, 434 // * repeated calls to {@code trySplit()} must eventually return {@code null}. 435 // * Upon non-null return: 436 // * <ul> 437 // * <li>the value reported for {@code estimateSize()} before splitting, 438 // * must, after splitting, be greater than or equal to {@code estimateSize()} 439 // * for this and the returned Spliterator; and</li> 440 // * <li>if this Spliterator is {@code SUBSIZED}, then {@code estimateSize()} 441 // * for this spliterator before splitting must be equal to the sum of 442 // * {@code estimateSize()} for this and the returned Spliterator after 443 // * splitting.</li> 444 // * </ul> 445 // * 446 // * <p>This method may return {@code null} for any reason, 447 // * including emptiness, inability to split after traversal has 448 // * commenced, data structure constraints, and efficiency 449 // * considerations. 450 // * 451 // * @apiNote 452 // * An ideal {@code trySplit} method efficiently (without 453 // * traversal) divides its elements exactly in half, allowing 454 // * balanced parallel computation. Many departures from this ideal 455 // * remain highly effective; for example, only approximately 456 // * splitting an approximately balanced tree, or for a tree in 457 // * which leaf nodes may contain either one or two elements, 458 // * failing to further split these nodes. However, large 459 // * deviations in balance and/or overly inefficient {@code 460 // * trySplit} mechanics typically result in poor parallel 461 // * performance. 462 // * 463 // * @return a {@code Spliterator} covering some portion of the 464 // * elements, or {@code null} if this spliterator cannot be split 465 // */ 466 // Spliterator!(T) trySplit(); 467 468 // /** 469 // * Returns an estimate of the number of elements that would be 470 // * encountered by a {@link #forEachRemaining} traversal, or returns {@link 471 // * Long#MAX_VALUE} if infinite, unknown, or too expensive to compute. 472 // * 473 // * <p>If this Spliterator is {@link #SIZED} and has not yet been partially 474 // * traversed or split, or this Spliterator is {@link #SUBSIZED} and has 475 // * not yet been partially traversed, this estimate must be an accurate 476 // * count of elements that would be encountered by a complete traversal. 477 // * Otherwise, this estimate may be arbitrarily inaccurate, but must decrease 478 // * as specified across invocations of {@link #trySplit}. 479 // * 480 // * @apiNote 481 // * Even an inexact estimate is often useful and inexpensive to compute. 482 // * For example, a sub-spliterator of an approximately balanced binary tree 483 // * may return a value that estimates the number of elements to be half of 484 // * that of its parent; if the root Spliterator does not maintain an 485 // * accurate count, it could estimate size to be the power of two 486 // * corresponding to its maximum depth. 487 // * 488 // * @return the estimated size, or {@code Long.MAX_VALUE} if infinite, 489 // * unknown, or too expensive to compute. 490 // */ 491 // long estimateSize(); 492 493 // /** 494 // * Convenience method that returns {@link #estimateSize()} if this 495 // * Spliterator is {@link #SIZED}, else {@code -1}. 496 // * @implSpec 497 // * The default implementation returns the result of {@code estimateSize()} 498 // * if the Spliterator reports a characteristic of {@code SIZED}, and 499 // * {@code -1} otherwise. 500 // * 501 // * @return the exact size, if known, else {@code -1}. 502 // */ 503 // default long getExactSizeIfKnown() { 504 // return (characteristics() & SIZED) == 0 ? -1L : estimateSize(); 505 // } 506 507 // /** 508 // * Returns a set of characteristics of this Spliterator and its 509 // * elements. The result is represented as ORed values from {@link 510 // * #ORDERED}, {@link #DISTINCT}, {@link #SORTED}, {@link #SIZED}, 511 // * {@link #NONNULL}, {@link #IMMUTABLE}, {@link #CONCURRENT}, 512 // * {@link #SUBSIZED}. Repeated calls to {@code characteristics()} on 513 // * a given spliterator, prior to or in-between calls to {@code trySplit}, 514 // * should always return the same result. 515 // * 516 // * <p>If a Spliterator reports an inconsistent set of 517 // * characteristics (either those returned from a single invocation 518 // * or across multiple invocations), no guarantees can be made 519 // * about any computation using this Spliterator. 520 // * 521 // * @apiNote The characteristics of a given spliterator before splitting 522 // * may differ from the characteristics after splitting. For specific 523 // * examples see the characteristic values {@link #SIZED}, {@link #SUBSIZED} 524 // * and {@link #CONCURRENT}. 525 // * 526 // * @return a representation of characteristics 527 // */ 528 // int characteristics(); 529 530 // /** 531 // * Returns {@code true} if this Spliterator's {@link 532 // * #characteristics} contain all of the given characteristics. 533 // * 534 // * @implSpec 535 // * The default implementation returns true if the corresponding bits 536 // * of the given characteristics are set. 537 // * 538 // * @param characteristics the characteristics to check for 539 // * @return {@code true} if all the specified characteristics are present, 540 // * else {@code false} 541 // */ 542 // default bool hasCharacteristics(int characteristics) { 543 // return (characteristics() & characteristics) == characteristics; 544 // } 545 546 // /** 547 // * If this Spliterator's source is {@link #SORTED} by a {@link Comparator}, 548 // * returns that {@code Comparator}. If the source is {@code SORTED} in 549 // * {@linkplain Comparable natural order}, returns {@code null}. Otherwise, 550 // * if the source is not {@code SORTED}, throws {@link IllegalStateException}. 551 // * 552 // * @implSpec 553 // * The default implementation always throws {@link IllegalStateException}. 554 // * 555 // * @return a Comparator, or {@code null} if the elements are sorted in the 556 // * natural order. 557 // * @throws IllegalStateException if the spliterator does not report 558 // * a characteristic of {@code SORTED}. 559 // */ 560 // default Comparator<T> getComparator() { 561 // throw new IllegalStateException(); 562 // } 563 564 565 566 // /** 567 // * A Spliterator specialized for primitive values. 568 // * 569 // * @param (T) the type of elements returned by this Spliterator. The 570 // * type must be a wrapper type for a primitive type, such as {@code Integer} 571 // * for the primitive {@code int} type. 572 // * @param <T_CONS> the type of primitive consumer. The type must be a 573 // * primitive specialization of {@link hunt.util.functional.Consumer} for 574 // * {@code T}, such as {@link hunt.util.functional.IntConsumer} for 575 // * {@code Integer}. 576 // * @param <T_SPLITR> the type of primitive Spliterator. The type must be 577 // * a primitive specialization of Spliterator for {@code T}, such as 578 // * {@link Spliterator.OfInt} for {@code Integer}. 579 // * 580 // * @see Spliterator.OfInt 581 // * @see Spliterator.OfLong 582 // * @see Spliterator.OfDouble 583 // * @since 1.8 584 // */ 585 // public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>> 586 // extends Spliterator!(T) { 587 // @Override 588 // T_SPLITR trySplit(); 589 590 // /** 591 // * If a remaining element exists, performs the given action on it, 592 // * returning {@code true}; else returns {@code false}. If this 593 // * Spliterator is {@link #ORDERED} the action is performed on the 594 // * next element in encounter order. Exceptions thrown by the 595 // * action are relayed to the caller. 596 // * 597 // * @param action The action 598 // * @return {@code false} if no remaining elements existed 599 // * upon entry to this method, else {@code true}. 600 // * @throws NullPointerException if the specified action is null 601 // */ 602 // 603 // bool tryAdvance(T_CONS action); 604 605 // /** 606 // * Performs the given action for each remaining element, sequentially in 607 // * the current thread, until all elements have been processed or the 608 // * action throws an exception. If this Spliterator is {@link #ORDERED}, 609 // * actions are performed in encounter order. Exceptions thrown by the 610 // * action are relayed to the caller. 611 // * 612 // * @implSpec 613 // * The default implementation repeatedly invokes {@link #tryAdvance} 614 // * until it returns {@code false}. It should be overridden whenever 615 // * possible. 616 // * 617 // * @param action The action 618 // * @throws NullPointerException if the specified action is null 619 // */ 620 // 621 // default void forEachRemaining(T_CONS action) { 622 // do { } while (tryAdvance(action)); 623 // } 624 // } 625 626 // /** 627 // * A Spliterator specialized for {@code int} values. 628 // * @since 1.8 629 // */ 630 // public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> { 631 632 // @Override 633 // OfInt trySplit(); 634 635 // @Override 636 // bool tryAdvance(IntConsumer action); 637 638 // @Override 639 // default void forEachRemaining(IntConsumer action) { 640 // do { } while (tryAdvance(action)); 641 // } 642 643 // /** 644 // * {@inheritDoc} 645 // * @implSpec 646 // * If the action is an instance of {@code IntConsumer} then it is cast 647 // * to {@code IntConsumer} and passed to 648 // * {@link #tryAdvance(hunt.util.functional.IntConsumer)}; otherwise 649 // * the action is adapted to an instance of {@code IntConsumer}, by 650 // * boxing the argument of {@code IntConsumer}, and then passed to 651 // * {@link #tryAdvance(hunt.util.functional.IntConsumer)}. 652 // */ 653 // @Override 654 // default bool tryAdvance(Consumer<Integer> action) { 655 // if (action instanceof IntConsumer) { 656 // return tryAdvance((IntConsumer) action); 657 // } 658 // else { 659 // if (Tripwire.ENABLED) 660 // Tripwire.trip(getClass(), 661 // "{0} calling Spliterator.OfInt.tryAdvance((IntConsumer) action::accept)"); 662 // return tryAdvance((IntConsumer) action::accept); 663 // } 664 // } 665 666 // /** 667 // * {@inheritDoc} 668 // * @implSpec 669 // * If the action is an instance of {@code IntConsumer} then it is cast 670 // * to {@code IntConsumer} and passed to 671 // * {@link #forEachRemaining(hunt.util.functional.IntConsumer)}; otherwise 672 // * the action is adapted to an instance of {@code IntConsumer}, by 673 // * boxing the argument of {@code IntConsumer}, and then passed to 674 // * {@link #forEachRemaining(hunt.util.functional.IntConsumer)}. 675 // */ 676 // @Override 677 // default void forEachRemaining(Consumer<Integer> action) { 678 // if (action instanceof IntConsumer) { 679 // forEachRemaining((IntConsumer) action); 680 // } 681 // else { 682 // if (Tripwire.ENABLED) 683 // Tripwire.trip(getClass(), 684 // "{0} calling Spliterator.OfInt.forEachRemaining((IntConsumer) action::accept)"); 685 // forEachRemaining((IntConsumer) action::accept); 686 // } 687 // } 688 // } 689 690 // /** 691 // * A Spliterator specialized for {@code long} values. 692 // * @since 1.8 693 // */ 694 // public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> { 695 696 // @Override 697 // OfLong trySplit(); 698 699 // @Override 700 // bool tryAdvance(LongConsumer action); 701 702 // @Override 703 // default void forEachRemaining(LongConsumer action) { 704 // do { } while (tryAdvance(action)); 705 // } 706 707 // /** 708 // * {@inheritDoc} 709 // * @implSpec 710 // * If the action is an instance of {@code LongConsumer} then it is cast 711 // * to {@code LongConsumer} and passed to 712 // * {@link #tryAdvance(hunt.util.functional.LongConsumer)}; otherwise 713 // * the action is adapted to an instance of {@code LongConsumer}, by 714 // * boxing the argument of {@code LongConsumer}, and then passed to 715 // * {@link #tryAdvance(hunt.util.functional.LongConsumer)}. 716 // */ 717 // @Override 718 // default bool tryAdvance(Consumer<Long> action) { 719 // if (action instanceof LongConsumer) { 720 // return tryAdvance((LongConsumer) action); 721 // } 722 // else { 723 // if (Tripwire.ENABLED) 724 // Tripwire.trip(getClass(), 725 // "{0} calling Spliterator.OfLong.tryAdvance((LongConsumer) action::accept)"); 726 // return tryAdvance((LongConsumer) action::accept); 727 // } 728 // } 729 730 // /** 731 // * {@inheritDoc} 732 // * @implSpec 733 // * If the action is an instance of {@code LongConsumer} then it is cast 734 // * to {@code LongConsumer} and passed to 735 // * {@link #forEachRemaining(hunt.util.functional.LongConsumer)}; otherwise 736 // * the action is adapted to an instance of {@code LongConsumer}, by 737 // * boxing the argument of {@code LongConsumer}, and then passed to 738 // * {@link #forEachRemaining(hunt.util.functional.LongConsumer)}. 739 // */ 740 // @Override 741 // default void forEachRemaining(Consumer<Long> action) { 742 // if (action instanceof LongConsumer) { 743 // forEachRemaining((LongConsumer) action); 744 // } 745 // else { 746 // if (Tripwire.ENABLED) 747 // Tripwire.trip(getClass(), 748 // "{0} calling Spliterator.OfLong.forEachRemaining((LongConsumer) action::accept)"); 749 // forEachRemaining((LongConsumer) action::accept); 750 // } 751 // } 752 // } 753 754 // /** 755 // * A Spliterator specialized for {@code double} values. 756 // * @since 1.8 757 // */ 758 // public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> { 759 760 // @Override 761 // OfDouble trySplit(); 762 763 // @Override 764 // bool tryAdvance(DoubleConsumer action); 765 766 // @Override 767 // default void forEachRemaining(DoubleConsumer action) { 768 // do { } while (tryAdvance(action)); 769 // } 770 771 // /** 772 // * {@inheritDoc} 773 // * @implSpec 774 // * If the action is an instance of {@code DoubleConsumer} then it is 775 // * cast to {@code DoubleConsumer} and passed to 776 // * {@link #tryAdvance(hunt.util.functional.DoubleConsumer)}; otherwise 777 // * the action is adapted to an instance of {@code DoubleConsumer}, by 778 // * boxing the argument of {@code DoubleConsumer}, and then passed to 779 // * {@link #tryAdvance(hunt.util.functional.DoubleConsumer)}. 780 // */ 781 // @Override 782 // default bool tryAdvance(Consumer<Double> action) { 783 // if (action instanceof DoubleConsumer) { 784 // return tryAdvance((DoubleConsumer) action); 785 // } 786 // else { 787 // if (Tripwire.ENABLED) 788 // Tripwire.trip(getClass(), 789 // "{0} calling Spliterator.OfDouble.tryAdvance((DoubleConsumer) action::accept)"); 790 // return tryAdvance((DoubleConsumer) action::accept); 791 // } 792 // } 793 794 // /** 795 // * {@inheritDoc} 796 // * @implSpec 797 // * If the action is an instance of {@code DoubleConsumer} then it is 798 // * cast to {@code DoubleConsumer} and passed to 799 // * {@link #forEachRemaining(hunt.util.functional.DoubleConsumer)}; 800 // * otherwise the action is adapted to an instance of 801 // * {@code DoubleConsumer}, by boxing the argument of 802 // * {@code DoubleConsumer}, and then passed to 803 // * {@link #forEachRemaining(hunt.util.functional.DoubleConsumer)}. 804 // */ 805 // @Override 806 // default void forEachRemaining(Consumer<Double> action) { 807 // if (action instanceof DoubleConsumer) { 808 // forEachRemaining((DoubleConsumer) action); 809 // } 810 // else { 811 // if (Tripwire.ENABLED) 812 // Tripwire.trip(getClass(), 813 // "{0} calling Spliterator.OfDouble.forEachRemaining((DoubleConsumer) action::accept)"); 814 // forEachRemaining((DoubleConsumer) action::accept); 815 // } 816 // } 817 // } 818 }