1 /* 2 * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.util.stream; 26 27 import java.util.EnumMap; 28 import java.util.Map; 29 import java.util.Spliterator; 30 31 /** 32 * Flags corresponding to characteristics of streams and operations. Flags are 33 * utilized by the stream framework to control, specialize or optimize 34 * computation. 35 * 36 * <p> 37 * Stream flags may be used to describe characteristics of several different 38 * entities associated with streams: stream sources, intermediate operations, 39 * and terminal operations. Not all stream flags are meaningful for all 40 * entities; the following table summarizes which flags are meaningful in what 41 * contexts: 42 * <pre> 43 * DISTINCT SORTED ORDERED SIZED SHORT_CIRCUIT PARALLEL 44 * Stream source Y Y Y Y N Y 45 * Intermediate operation PCI PCI PCI PC PI PC 46 * Terminal operation N N PC N PI N 47 * </pre> 48 * 49 * <p>In the above table, "PCI" means "may preserve, clear, or inject"; "PC" 50 * means "may preserve or clear", "PI" means "may preserve or inject", and "N" 51 * means "not valid". 52 * 53 * <p>Stream flags are represented by unioned bit sets, so that a single word 54 * may describe all the characteristics of a given stream entity, and that, for 55 * example, the flags for a stream source can be efficiently combined with the 56 * flags for later operations on that stream. 57 * 58 * <p>The bit masks {@link #STREAM_MASK}, {@link #OP_MASK}, and 59 * {@link #TERMINAL_OP_MASK} can be ANDed with a bit set of stream flags to 60 * produce a mask containing only the valid flags for that entity type. 61 * 62 * <p>When describing a stream source, one only need describe what 63 * characteristics that stream has; when describing a stream operation, one need 64 * describe whether the operation preserves, injects, or clears that 65 * characteristic. Accordingly, two bits are used for each flag, so as to allow 66 * representing not only the presence of of a characteristic, but how an 67 * operation modifies that characteristic. There are two common forms in which 68 * flag bits are combined into an {@code int} bit set. <em>Stream flags</em> 69 * are a unioned bit set constructed by ORing the enum characteristic values of 70 * {@link #set()} (or, more commonly, ORing the corresponding static named 71 * constants prefixed with {@code IS_}). <em>Operation flags</em> are a unioned 72 * bit set constructed by ORing the enum characteristic values of {@link #set()} 73 * or {@link #clear()} (to inject, or clear, respectively, the corresponding 74 * flag), or more commonly ORing the corresponding named constants prefixed with 75 * {@code IS_} or {@code NOT_}. Flags that are not marked with {@code IS_} or 76 * {@code NOT_} are implicitly treated as preserved. Care must be taken when 77 * combining bitsets that the correct combining operations are applied in the 78 * correct order. 79 * 80 * <p> 81 * With the exception of {@link #PARALLEL}, stream characteristics can be 82 * derived from the equivalent {@link java.util.Spliterator} characteristics: 83 * {@link java.util.Spliterator#DISTINCT}, {@link java.util.Spliterator#SORTED}, 84 * {@link java.util.Spliterator#ORDERED}, and 85 * {@link java.util.Spliterator#SIZED}. A spliterator characteristics bit set 86 * can be converted to stream flags using the method 87 * {@link #fromCharacteristics(java.util.Spliterator)} and converted back using 88 * {@link #toCharacteristics(int)}. (The bit set 89 * {@link #SPLITERATOR_CHARACTERISTICS_MASK} is used to AND with a bit set to 90 * produce a valid spliterator characteristics bit set that can be converted to 91 * stream flags.) 92 * 93 * <p> 94 * The source of a stream encapsulates a spliterator. The characteristics of 95 * that source spliterator when transformed to stream flags will be a proper 96 * subset of stream flags of that stream. 97 * For example: 98 * <pre> {@code 99 * Spliterator s = ...; 100 * Stream stream = Streams.stream(s); 101 * flagsFromSplitr = fromCharacteristics(s.characteristics()); 102 * assert(flagsFromSplitr & stream.getStreamFlags() == flagsFromSplitr); 103 * }</pre> 104 * 105 * <p> 106 * An intermediate operation, performed on an input stream to create a new 107 * output stream, may preserve, clear or inject stream or operation 108 * characteristics. Similarly, a terminal operation, performed on an input 109 * stream to produce an output result may preserve, clear or inject stream or 110 * operation characteristics. Preservation means that if that characteristic 111 * is present on the input, then it is also present on the output. Clearing 112 * means that the characteristic is not present on the output regardless of the 113 * input. Injection means that the characteristic is present on the output 114 * regardless of the input. If a characteristic is not cleared or injected then 115 * it is implicitly preserved. 116 * 117 * <p> 118 * A pipeline consists of a stream source encapsulating a spliterator, one or 119 * more intermediate operations, and finally a terminal operation that produces 120 * a result. At each stage of the pipeline, a combined stream and operation 121 * flags can be calculated, using {@link #combineOpFlags(int, int)}. Such flags 122 * ensure that preservation, clearing and injecting information is retained at 123 * each stage. 124 * 125 * The combined stream and operation flags for the source stage of the pipeline 126 * is calculated as follows: 127 * <pre> {@code 128 * int flagsForSourceStage = combineOpFlags(sourceFlags, INITIAL_OPS_VALUE); 129 * }</pre> 130 * 131 * The combined stream and operation flags of each subsequent intermediate 132 * operation stage in the pipeline is calculated as follows: 133 * <pre> {@code 134 * int flagsForThisStage = combineOpFlags(flagsForPreviousStage, thisOpFlags); 135 * }</pre> 136 * 137 * Finally the flags output from the last intermediate operation of the pipeline 138 * are combined with the operation flags of the terminal operation to produce 139 * the flags output from the pipeline. 140 * 141 * <p>Those flags can then be used to apply optimizations. For example, if 142 * {@code SIZED.isKnown(flags)} returns true then the stream size remains 143 * constant throughout the pipeline, this information can be utilized to 144 * pre-allocate data structures and combined with 145 * {@link java.util.Spliterator#SUBSIZED} that information can be utilized to 146 * perform concurrent in-place updates into a shared array. 147 * 148 * For specific details see the {@link AbstractPipeline} constructors. 149 * 150 * @since 1.8 151 */ 152 // @@@ When a new flag is added what should happen for existing operations? 153 // Need to move to a builder approach used by ops where the masks for the new flag are 154 // taken into account for default behaviour. 155 enum StreamOpFlag { 156 157 /* 158 * Each characteristic takes up 2 bits in a bit set to accommodate 159 * preserving, clearing and setting/injecting information. 160 * 161 * This applies to stream flags, intermediate/terminal operation flags, and 162 * combined stream and operation flags. Even though the former only requires 163 * 1 bit of information per characteristic, is it more efficient when 164 * combining flags to align set and inject bits. 165 * 166 * Characteristics belong to certain types, see the Type enum. Bit masks for 167 * the types are constructed as per the following table: 168 * 169 * DISTINCT SORTED ORDERED SIZED SHORT_CIRCUIT PARALLEL 170 * SPLITERATOR 01 01 01 01 00 00 171 * STREAM 01 01 01 01 00 01 172 * OP 11 11 11 10 01 10 173 * TERMINAL_OP 00 00 10 00 01 00 174 * UPSTREAM_TERMINAL_OP 00 00 10 00 00 00 175 * 176 * 01 = set/inject 177 * 10 = clear 178 * 11 = preserve 179 * 180 * Construction of the columns is performed using a simple builder for 181 * non-zero values. 182 */ 183 184 185 // The following flags correspond to characteristics on Spliterator 186 // and the values MUST be equal. 187 // 188 189 /** 190 * Characteristic value signifying that, for each pair of 191 * encountered elements in a stream {@code x, y}, {@code !x.equals(y)}. 192 * <p> 193 * A stream may have this value or an intermediate operation can preserve, 194 * clear or inject this value. 195 */ 196 // 0, 0x00000001 197 // Matches Spliterator.DISTINCT 198 DISTINCT(0, 199 set(Type.SPLITERATOR).set(Type.STREAM).setAndClear(Type.OP)), 200 201 /** 202 * Characteristic value signifying that encounter order follows a natural 203 * sort order of comparable elements. 204 * <p> 205 * A stream can have this value or an intermediate operation can preserve, 206 * clear or inject this value. 207 * <p> 208 * Note: The {@link java.util.Spliterator#SORTED} characteristic can define 209 * a sort order with an associated non-null comparator. Augmenting flag 210 * state with addition properties such that those properties can be passed 211 * to operations requires some disruptive changes for a singular use-case. 212 * Furthermore, comparing comparators for equality beyond that of identity 213 * is likely to be unreliable. Therefore the {@code SORTED} characteristic 214 * for a defined non-natural sort order is not mapped internally to the 215 * {@code SORTED} flag. 216 */ 217 // 1, 0x00000004 218 // Matches Spliterator.SORTED 219 SORTED(1, 220 set(Type.SPLITERATOR).set(Type.STREAM).setAndClear(Type.OP)), 221 222 /** 223 * Characteristic value signifying that an encounter order is 224 * defined for stream elements. 225 * <p> 226 * A stream can have this value, an intermediate operation can preserve, 227 * clear or inject this value, or a terminal operation can preserve or clear 228 * this value. 229 */ 230 // 2, 0x00000010 231 // Matches Spliterator.ORDERED 232 ORDERED(2, 233 set(Type.SPLITERATOR).set(Type.STREAM).setAndClear(Type.OP).clear(Type.TERMINAL_OP) 234 .clear(Type.UPSTREAM_TERMINAL_OP)), 235 236 /** 237 * Characteristic value signifying that size of the stream 238 * is of a known finite size that is equal to the known finite 239 * size of the source spliterator input to the first stream 240 * in the pipeline. 241 * <p> 242 * A stream can have this value or an intermediate operation can preserve or 243 * clear this value. 244 */ 245 // 3, 0x00000040 246 // Matches Spliterator.SIZED 247 SIZED(3, 248 set(Type.SPLITERATOR).set(Type.STREAM).clear(Type.OP)), 249 250 // The following Spliterator characteristics are not currently used but a 251 // gap in the bit set is deliberately retained to enable corresponding 252 // stream flags if//when required without modification to other flag values. 253 // 254 // 4, 0x00000100 INFINITE(4, ... 255 // 5, 0x00000400 NONNULL(5, ... 256 // 6, 0x00001000 IMMUTABLE(6, ... 257 // 7, 0x00004000 CONCURRENT(7, ... 258 // 8, 0x00010000 SUBSIZED(8, ...) 259 260 // The following 3 flags are currently undefined and a free for any further 261 // spliterator characteristics. 262 // 263 // 9, 0x00040000 264 // 10, 0x00100000 265 // 11, 0x00400000 266 267 // The following flags are specific to streams and operations 268 // 269 270 /** 271 * Characteristic value signifying that an operation may short-circuit the 272 * stream. 273 * <p> 274 * An intermediate operation can preserve or inject this value, 275 * or a terminal operation can preserve or inject this value. 276 */ 277 // 12, 0x01000000 278 SHORT_CIRCUIT(12, 279 set(Type.OP).set(Type.TERMINAL_OP)), 280 281 282 /** 283 * Characteristic value signifying that the stream is to be evaluated in 284 * parallel rather than sequentially. 285 * <p> 286 * A stream can have this value or an intermediate operation can preserve or 287 * clear this value. 288 */ 289 // 13, 0x04000000 290 PARALLEL(13, 291 set(Type.STREAM).clear(Type.OP)); 292 293 // The following 2 flags are currently undefined and a free for any further 294 // stream flags if/when required 295 // 296 // 14, 0x10000000 297 // 15, 0x40000000 298 299 /** 300 * Type of a flag 301 */ 302 enum Type { 303 /** The flag is associated with spliterator characteristics. */ 304 SPLITERATOR, 305 306 /** The flag is associated with stream flags. */ 307 STREAM, 308 309 /** The flag is associated with intermediate operation flags. */ 310 OP, 311 312 /** The flag is associated with terminal operation flags. */ 313 TERMINAL_OP, 314 315 /** 316 * The flag is associated with terminal operation flags that are 317 * propagated upstream across the last stateful operation boundary 318 */ 319 UPSTREAM_TERMINAL_OP 320 } 321 322 /** 323 * The bit pattern for setting/injecting a flag. 324 */ 325 private static final int SET_BITS = 0b01; 326 327 /** 328 * The bit pattern for clearing a flag. 329 */ 330 private static final int CLEAR_BITS = 0b10; 331 332 /** 333 * The bit pattern for preserving a flag. 334 */ 335 private static final int PRESERVE_BITS = 0b11; 336 337 private static MaskBuilder set(Type t) { 338 return new MaskBuilder(new EnumMap<>(Type.class)).set(t); 339 } 340 341 private static class MaskBuilder { 342 final Map<Type, Integer> map; 343 344 MaskBuilder(Map<Type, Integer> map) { 345 this.map = map; 346 } 347 348 MaskBuilder mask(Type t, Integer i) { 349 map.put(t, i); 350 return this; 351 } 352 353 MaskBuilder set(Type t) { 354 return mask(t, SET_BITS); 355 } 356 357 MaskBuilder clear(Type t) { 358 return mask(t, CLEAR_BITS); 359 } 360 361 MaskBuilder setAndClear(Type t) { 362 return mask(t, PRESERVE_BITS); 363 } 364 365 Map<Type, Integer> build() { 366 for (Type t : Type.values()) { 367 map.putIfAbsent(t, 0b00); 368 } 369 return map; 370 } 371 } 372 373 // The mask table for a flag, this is used to determine 374 // if a flag corresponds to a certain flag type and for creating 375 // mask constants. 376 private final Map<Type, Integer> maskTable; 377 378 // The bit position in the bit mask 379 private final int bitPosition; 380 381 // The set 2 bit set offset at the bit position 382 private final int set; 383 384 // The clear 2 bit set offset at the bit position 385 private final int clear; 386 387 // The preserve 2 bit set offset at the bit position 388 private final int preserve; 389 390 private StreamOpFlag(int position, MaskBuilder maskBuilder) { 391 this.maskTable = maskBuilder.build(); 392 // Two bits per flag 393 position *= 2; 394 this.bitPosition = position; 395 this.set = SET_BITS << position; 396 this.clear = CLEAR_BITS << position; 397 this.preserve = PRESERVE_BITS << position; 398 } 399 400 /** 401 * Gets the bitmap associated with setting this characteristic 402 * @return the bitmap for setting this characteristic 403 */ 404 int set() { 405 return set; 406 } 407 408 /** 409 * Gets the bitmap associated with clearing this characteristic 410 * @return the bitmap for clearing this characteristic 411 */ 412 int clear() { 413 return clear; 414 } 415 416 /** 417 * Determines if this flag is a stream-based flag. 418 * 419 * @return true if a stream-based flag, otherwise false. 420 */ 421 boolean isStreamFlag() { 422 return maskTable.get(Type.STREAM) > 0; 423 } 424 425 /** 426 * Checks if this flag is set on stream flags, injected on operation flags, 427 * and injected on combined stream and operation flags. 428 * 429 * @param flags the stream flags, operation flags, or combined stream and 430 * operation flags 431 * @return true if this flag is known, otherwise false. 432 */ 433 boolean isKnown(int flags) { 434 return (flags & preserve) == set; 435 } 436 437 /** 438 * Checks if this flag is cleared on operation flags or combined stream and 439 * operation flags. 440 * 441 * @param flags the operation flags or combined stream and operations flags. 442 * @return true if this flag is preserved, otherwise false. 443 */ 444 boolean isCleared(int flags) { 445 return (flags & preserve) == clear; 446 } 447 448 /** 449 * Checks if this flag is preserved on combined stream and operation flags. 450 * 451 * @param flags the combined stream and operations flags. 452 * @return true if this flag is preserved, otherwise false. 453 */ 454 boolean isPreserved(int flags) { 455 return (flags & preserve) == preserve; 456 } 457 458 /** 459 * Determines if this flag can be set for a flag type. 460 * 461 * @param t the flag type. 462 * @return true if this flag can be set for the flag type, otherwise false. 463 */ 464 boolean canSet(Type t) { 465 return (maskTable.get(t) & SET_BITS) > 0; 466 } 467 468 /** 469 * The bit mask for spliterator characteristics 470 */ 471 static final int SPLITERATOR_CHARACTERISTICS_MASK = createMask(Type.SPLITERATOR); 472 473 /** 474 * The bit mask for source stream flags. 475 */ 476 static final int STREAM_MASK = createMask(Type.STREAM); 477 478 /** 479 * The bit mask for intermediate operation flags. 480 */ 481 static final int OP_MASK = createMask(Type.OP); 482 483 /** 484 * The bit mask for terminal operation flags. 485 */ 486 static final int TERMINAL_OP_MASK = createMask(Type.TERMINAL_OP); 487 488 /** 489 * The bit mask for upstream terminal operation flags. 490 */ 491 static final int UPSTREAM_TERMINAL_OP_MASK = createMask(Type.UPSTREAM_TERMINAL_OP); 492 493 private static int createMask(Type t) { 494 int mask = 0; 495 for (StreamOpFlag flag : StreamOpFlag.values()) { 496 mask |= flag.maskTable.get(t) << flag.bitPosition; 497 } 498 return mask; 499 } 500 501 // Complete flag mask 502 private static final int FLAG_MASK = createFlagMask(); 503 504 private static int createFlagMask() { 505 int mask = 0; 506 for (StreamOpFlag flag : StreamOpFlag.values()) { 507 mask |= flag.preserve; 508 } 509 return mask; 510 } 511 512 // Flag mask for stream flags that are set 513 private static final int FLAG_MASK_IS = STREAM_MASK; 514 515 // Flag mask for stream flags that are cleared 516 private static final int FLAG_MASK_NOT = STREAM_MASK << 1; 517 518 /** 519 * The initial value to be combined with the stream flags of the first 520 * stream in the pipeline. 521 */ 522 static final int INITIAL_OPS_VALUE = FLAG_MASK_IS | FLAG_MASK_NOT; 523 524 /** 525 * The bit value to set or inject {@link #DISTINCT} 526 */ 527 static final int IS_DISTINCT = DISTINCT.set; 528 529 /** 530 * The bit value to clear {@link #DISTINCT} 531 */ 532 static final int NOT_DISTINCT = DISTINCT.clear; 533 534 /** 535 * The bit value to set or inject {@link #SORTED} 536 */ 537 static final int IS_SORTED = SORTED.set; 538 539 /** 540 * The bit value to clear {@link #SORTED} 541 */ 542 static final int NOT_SORTED = SORTED.clear; 543 544 /** 545 * The bit value to set or inject {@link #ORDERED} 546 */ 547 static final int IS_ORDERED = ORDERED.set; 548 549 /** 550 * The bit value to clear {@link #ORDERED} 551 */ 552 static final int NOT_ORDERED = ORDERED.clear; 553 554 /** 555 * The bit value to set {@link #SIZED} 556 */ 557 static final int IS_SIZED = SIZED.set; 558 559 /** 560 * The bit value to clear {@link #SIZED} 561 */ 562 static final int NOT_SIZED = SIZED.clear; 563 564 /** 565 * The bit value to inject {@link #SHORT_CIRCUIT} 566 */ 567 static final int IS_SHORT_CIRCUIT = SHORT_CIRCUIT.set; 568 569 /** 570 * The bit value to set {@link #PARALLEL} 571 */ 572 static final int IS_PARALLEL = PARALLEL.set; 573 574 /** 575 * The bit value to clear {@link #PARALLEL} 576 */ 577 static final int NOT_PARALLEL = PARALLEL.clear; 578 579 private static int getMask(int flags) { 580 return (flags == 0) 581 ? FLAG_MASK 582 : ~(flags | ((FLAG_MASK_IS & flags) << 1) | ((FLAG_MASK_NOT & flags) >> 1)); 583 } 584 585 /** 586 * Combines stream or operation flags with previously combined stream and 587 * operation flags to produce updated combined stream and operation flags. 588 * <p> 589 * A flag set on stream flags or injected on operation flags, 590 * and injected combined stream and operation flags, 591 * will be injected on the updated combined stream and operation flags. 592 * </p> 593 * <p> 594 * A flag set on stream flags or injected on operation flags, 595 * and cleared on the combined stream and operation flags, 596 * will be cleared on the updated combined stream and operation flags. 597 * </p> 598 * <p> 599 * A flag set on the stream flags or injected on operation flags, 600 * and preserved on the combined stream and operation flags, 601 * will be injected on the updated combined stream and operation flags. 602 * </p> 603 * <p> 604 * A flag not set on the stream flags or cleared/preserved on operation 605 * flags, and injected on the combined stream and operation flags, 606 * will be injected on the updated combined stream and operation flags. 607 * </p> 608 * <p> 609 * A flag not set on the stream flags or cleared/preserved on operation 610 * flags, and cleared on the combined stream and operation flags, 611 * will be cleared on the updated combined stream and operation flags. 612 * </p> 613 * <p> 614 * A flag not set on the stream flags, 615 * and preserved on the combined stream and operation flags 616 * will be preserved on the updated combined stream and operation flags. 617 * </p> 618 * <p> 619 * A flag cleared on operation flags, 620 * and preserved on the combined stream and operation flags 621 * will be cleared on the updated combined stream and operation flags. 622 * </p> 623 * <p> 624 * A flag preserved on operation flags, 625 * and preserved on the combined stream and operation flags 626 * will be preserved on the updated combined stream and operation flags. 627 * </p> 628 * 629 * @param newStreamOrOpFlags the stream or operation flags. 630 * @param prevCombOpFlags previously combined stream and operation flags. 631 * The value {#link INITIAL_OPS_VALUE} must be used as the seed value. 632 * @return the updated combined stream and operation flags. 633 */ 634 static int combineOpFlags(int newStreamOrOpFlags, int prevCombOpFlags) { 635 // 0x01 or 0x10 nibbles are transformed to 0x11 636 // 0x00 nibbles remain unchanged 637 // Then all the bits are flipped 638 // Then the result is logically or'ed with the operation flags. 639 return (prevCombOpFlags & StreamOpFlag.getMask(newStreamOrOpFlags)) | newStreamOrOpFlags; 640 } 641 642 /** 643 * Converts combined stream and operation flags to stream flags. 644 * 645 * <p>Each flag injected on the combined stream and operation flags will be 646 * set on the stream flags. 647 * 648 * @param combOpFlags the combined stream and operation flags. 649 * @return the stream flags. 650 */ 651 static int toStreamFlags(int combOpFlags) { 652 // By flipping the nibbles 0x11 become 0x00 and 0x01 become 0x10 653 // Shift left 1 to restore set flags and mask off anything other than the set flags 654 return ((~combOpFlags) >> 1) & FLAG_MASK_IS & combOpFlags; 655 } 656 657 /** 658 * Converts stream flags to a spliterator characteristic bit set. 659 * 660 * @param streamFlags the stream flags. 661 * @return the spliterator characteristic bit set. 662 */ 663 static int toCharacteristics(int streamFlags) { 664 return streamFlags & SPLITERATOR_CHARACTERISTICS_MASK; 665 } 666 667 /** 668 * Converts a spliterator characteristic bit set to stream flags. 669 * 670 * @implSpec 671 * If the spliterator is naturally {@code SORTED} (the associated 672 * {@code Comparator} is {@code null}) then the characteristic is converted 673 * to the {@link #SORTED} flag, otherwise the characteristic is not 674 * converted. 675 * 676 * @param spliterator the spliterator from which to obtain characteristic 677 * bit set. 678 * @return the stream flags. 679 */ 680 static int fromCharacteristics(Spliterator<?> spliterator) { 681 int characteristics = spliterator.characteristics(); 682 if ((characteristics & Spliterator.SORTED) != 0 && spliterator.getComparator() != null) { 683 // Do not propagate the SORTED characteristic if it does not correspond 684 // to a natural sort order 685 return characteristics & SPLITERATOR_CHARACTERISTICS_MASK & ~Spliterator.SORTED; 686 } 687 else { 688 return characteristics & SPLITERATOR_CHARACTERISTICS_MASK; 689 } 690 } 691 692 /** 693 * Converts a spliterator characteristic bit set to stream flags. 694 * 695 * @param characteristics the spliterator characteristic bit set. 696 * @return the stream flags. 697 */ 698 static int fromCharacteristics(int characteristics) { 699 return characteristics & SPLITERATOR_CHARACTERISTICS_MASK; 700 } 701 }