001/* 002 * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025package Torello.Java.ReadOnly; 026 027import Torello.Java.Additional.RemoveUnsupportedIterator; 028 029import Torello.JavaDoc.LinkJavaSource; 030import Torello.JavaDoc.IntoHTMLTable; 031 032import java.util.*; 033 034import java.io.Serializable; 035 036import java.util.stream.Collector; 037 038import java.util.function.Function; 039import java.util.function.Supplier; 040import java.util.function.Predicate; 041 042/** 043 * Immutable Wrapper for <CODE>java.util.TreeSet</CODE>, found in the "Java Collections 044 * Framework". 045 * 046 * <EMBED CLASS=globalDefs DATA-JDK=TreeSet> 047 * <EMBED CLASS='external-html' DATA-FILE-ID=MUCHOS_CONSTRUCTORS> 048 * <EMBED CLASS='external-html' DATA-FILE-ID=DATA_CLASS> 049 * 050 * @param <E> the type of elements maintained by this set 051 */ 052@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="JDHBI_MAIN") 053@SuppressWarnings("unchecked") 054public class ReadOnlyTreeSet<E> 055 implements ReadOnlyNavigableSet<E>, Serializable 056{ 057 // ******************************************************************************************** 058 // ******************************************************************************************** 059 // Protected & Private Fields, Methods, Statics 060 // ******************************************************************************************** 061 // ******************************************************************************************** 062 063 064 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 065 protected static final long serialVersionUID = 1; 066 067 // Minor Optimization where new TreeSet's that have no contents always re-use this static 068 // instance. Since this instance is completely empty, the Raw-Types things is irrelevant. 069 070 @SuppressWarnings("rawtypes") 071 private static final TreeSet EMPTY_TREE_SET = new TreeSet(); 072 073 // Singleton & Empty ReadOnlyTreeSet, Uses the "Supplier Constructor" 074 @SuppressWarnings("rawtypes") 075 private static final ReadOnlyTreeSet EMPTY_READONLY_TREE_SET = 076 new ReadOnlyTreeSet(null, () -> null); 077 078 // The actual TreeSet used by this instance. 079 private final TreeSet<E> treeSet; 080 081 // TRUE => This was built using the class ROTreeSetBuilder 082 // FALSE => This was built using the clone() of a standard java.util.TreeSet constructor 083 084 private final boolean fromBuilderOrTreeSet; 085 086 // Mimics the C++ Keyword/Concept of "Friend Class". Is "Friends With" ROTreeSetBuilder 087 static class AccessBadge { private AccessBadge() { } } 088 private static final AccessBadge friendClassBadge = new AccessBadge(); 089 090 /** 091 * Returns an empty, <B STYLE='color: red;'>singleton</B>, instance of {@code ReadOnlTreeSet}. 092 * @param <T> Returned {@link ReadOnlySet}'s Data-Type. 093 * 094 * @return An empty set. Since this set is both empty & read-only, a raw-type singleton 095 * will suffice for all operations offered by this clas. 096 * 097 * <EMBED CLASS='external-html' DATA-FILE-ID=EMPTY_SYNCHRONIZED> 098 */ 099 public static <T> ReadOnlyTreeSet<T> emptyROTS() 100 { return (ReadOnlyTreeSet<T>) EMPTY_READONLY_TREE_SET; } 101 102 103 // ******************************************************************************************** 104 // ******************************************************************************************** 105 // Basic Constructors 106 // ******************************************************************************************** 107 // ******************************************************************************************** 108 109 110 // To all the readers out there following along: The "AccessBadge" thing is just a slightly 111 // wimpier substitute for the C++ keyword / concept 'friend' or "Friend Class". It means this 112 // constructor is (for all intents and purposes) a private-constructor, except for the class 113 // ROTreeSetBuilder 114 // 115 // This is the Constructor used by the Builder. It has a "Zero-Size" Optimization 116 117 ReadOnlyTreeSet(ROTreeSetBuilder<E> rotsb, ROTreeSetBuilder.AccessBadge badge) 118 { 119 Objects.requireNonNull(badge, "Access Badge is null. Requires Friend-Class Badge"); 120 121 fromBuilderOrTreeSet = true; 122 this.treeSet = rotsb; 123 } 124 125 /** 126 * Copies parameter {@code 'c'} (and saves it) in order to guarantee that {@code 'this'} 127 * instance is Read-Only, and shielded from outside modification. 128 * 129 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 130 * 131 * @param c The {@code TreeSet} to be copied and saved into this instance internal 132 * and private {@code 'treeSet'} field. 133 */ 134 public ReadOnlyTreeSet(Collection<E> c) 135 { 136 fromBuilderOrTreeSet = false; 137 this.treeSet = (c.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : new TreeSet<>(c); 138 } 139 140 /** 141 * Copies parameter {@code 's'} (and saves it) in order to guarantee that {@code 'this'} 142 * instance is Read-Only, and shielded from outside modification. 143 * 144 * @param s The {@code TreeSet} to be copied and saved into this instance internal 145 * and private {@code 'treeSet'} field. 146 */ 147 public ReadOnlyTreeSet(SortedSet<E> s) 148 { 149 fromBuilderOrTreeSet = false; 150 this.treeSet = (s.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : new TreeSet<>(s); 151 } 152 153 /** 154 * Use a {@code Supplier<E>} to provide an arbitrary number of elements of type {@code 'E'} 155 * directly to this constructor. This constructor will request elements from the 156 * {@code Supplier} provided to parameter {@code 's'} until {@code 's'} returns null. 157 * 158 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 159 * 160 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 161 * @param s Any Java {@code Supplier<E>} 162 */ 163 public ReadOnlyTreeSet(Comparator<? super E> comparator, Supplier<E> s) 164 { 165 fromBuilderOrTreeSet = false; 166 167 final TreeSet<E> treeSet = (comparator != null) 168 ? new TreeSet<>(comparator) 169 : new TreeSet<>(); 170 171 E e; 172 while ((e = s.get()) != null) treeSet.add(e); 173 174 // Empty Optimization (throw away, completely, the reference, use static-constant) 175 this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet; 176 } 177 178 179 // ******************************************************************************************** 180 // ******************************************************************************************** 181 // Iterable & Array Based Constructors - **NO FILTER** 182 // ******************************************************************************************** 183 // ******************************************************************************************** 184 185 186 /** 187 * If only a small amount of processing needs to be done on the contents of some Java 188 * Data-Type, and using an entire Builder-Class seems disproportionately complex - <I>this 189 * constructor can convert any Java {@code Iterable} into a {@code ReadOnlyTreeSet}, using 190 * a simple {@code 'mapper'}</I>. 191 * 192 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 193 * 194 * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_TYPE_PARAM> 195 * @param i Any Java {@code Iterable} 196 * @param mapper <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_MAPPER> 197 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 198 * 199 * @throws NullPointerException if either {@code 'i'} or {@code 'mapper'} are passed null. 200 */ 201 public <T> ReadOnlyTreeSet( 202 Iterable<T> i, 203 Function<? super T, ? extends E> mapper, 204 Comparator<? super E> comparator 205 ) 206 { 207 Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'"); 208 209 fromBuilderOrTreeSet = false; 210 211 final TreeSet<E> treeSet = (comparator != null) 212 ? new TreeSet<>(comparator) 213 : new TreeSet<>(); 214 215 for (T t : i) treeSet.add(mapper.apply(t)); 216 217 // Empty Optimization (throw away, completely, the reference, use static-constant) 218 this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet; 219 } 220 221 /** 222 * If a Standard Java {@code Iterable} can be directly mapped into a {@code TreeSet} 223 * (and, ergo, an entire Builder-Instance would be a bit excessive) - <I>this constructor will 224 * seamlessly convert any Java {@code Iterable<E>} directly into a {@code ReadOnlyTreeSet<E>} 225 * with just this single invocation</I>. 226 * 227 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 228 * 229 * @param i Any Java {@code Iterable<E>} 230 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 231 */ 232 public ReadOnlyTreeSet(Iterable<E> i, Comparator<? super E> comparator) 233 { 234 fromBuilderOrTreeSet = false; 235 236 final TreeSet<E> treeSet = (comparator != null) 237 ? new TreeSet<>(comparator) 238 : new TreeSet<>(); 239 240 for (E element : i) treeSet.add(element); 241 242 // Empty Optimization (throw away, completely, the reference, use static-constant) 243 this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet; 244 } 245 246 /** 247 * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents 248 * {@code 'elements'}. 249 * 250 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 251 * 252 * @param elementsType <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_TYPE> 253 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 254 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 255 * 256 * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=CCEX> 257 * @throws NullPointerException If {@code 'elementsType'} is passed null. 258 */ 259 public ReadOnlyTreeSet 260 (Class<E> elementsType, Comparator<? super E> comparator, Object... elements) 261 { 262 Objects.requireNonNull(elementsType, ROHelpers.NULL_MSG + "'elementsType'"); 263 264 fromBuilderOrTreeSet = false; 265 266 if (elements.length == 0) 267 this.treeSet = (TreeSet<E>) EMPTY_TREE_SET; 268 269 else 270 { 271 this.treeSet = (comparator != null) 272 ? new TreeSet<>(comparator) 273 : new TreeSet<>(); 274 275 for (Object element : elements) this.treeSet.add(elementsType.cast(element)); 276 } 277 } 278 279 /** 280 * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents 281 * {@code 'elements'}. 282 * 283 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 284 * 285 * @param mapper <EMBED CLASS='external-html' DATA-FILE-ID=OBJ_E_MAPPER> 286 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 287 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 288 * 289 * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=CCEX> 290 * @throws NullPointerException If {@code 'mapper'} is passed null. 291 */ 292 public ReadOnlyTreeSet( 293 Function<Object, ? extends E> mapper, 294 Comparator<? super E> comparator, 295 Object... elements 296 ) 297 { 298 Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'"); 299 300 fromBuilderOrTreeSet = false; 301 302 if (elements.length == 0) 303 this.treeSet = (TreeSet<E>) EMPTY_TREE_SET; 304 305 else 306 { 307 this.treeSet = (comparator != null) 308 ? new TreeSet<>(comparator) 309 : new TreeSet<>(); 310 311 for (Object element : elements) this.treeSet.add(mapper.apply(element)); 312 } 313 } 314 315 316 // ******************************************************************************************** 317 // ******************************************************************************************** 318 // Iterable & Array Based Constructors - **INCLUDES ELEMENT FILTER** 319 // ******************************************************************************************** 320 // ******************************************************************************************** 321 322 323 /** 324 * If only a small amount of processing needs to be done on the contents of some Java 325 * Data-Type, and using an entire Builder-Class seems disproportionately complex - <I>this 326 * constructor can convert any Java {@code Iterable} into a {@code ReadOnlyTreeSet}, using 327 * a simple {@code 'mapper'}</I>. 328 * 329 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 330 * 331 * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_TYPE_PARAM> 332 * @param i Any Java {@code Iterable<T>} 333 * @param mapper <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_MAPPER> 334 * @param filter <EMBED CLASS='external-html' DATA-FTP=T DATA-FILE-ID=PREDICATE_FILTER> 335 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 336 * 337 * @throws NullPointerException if any of {@code 'i'}, {@code 'mapper'} or {@code 'filter'} are 338 * passed null 339 */ 340 public <T> ReadOnlyTreeSet( 341 Iterable<T> i, 342 Function<? super T, ? extends E> mapper, 343 Predicate<? super T> filter, 344 Comparator<? super E> comparator 345 ) 346 { 347 Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'"); 348 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 349 350 fromBuilderOrTreeSet = false; 351 352 final TreeSet<E> treeSet = (comparator != null) 353 ? new TreeSet<>(comparator) 354 : new TreeSet<>(); 355 356 for (T t : i) if (filter.test(t)) treeSet.add(mapper.apply(t)); 357 358 // Empty Optimization (throw away, completely, the reference, use static-constant) 359 this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet; 360 } 361 362 /** 363 * If a Standard Java {@code Iterable} can be directly mapped into a {@code TreeSet} 364 * (and, ergo, an entire Builder-Instance would be a bit excessive) - <I>this constructor will 365 * seamlessly convert any Java {@code Iterable<E>} directly into a {@code ReadOnlyTreeSet<E>} 366 * with just this single invocation</I>. 367 * 368 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 369 * 370 * @param i Any Java {@code Iterabler<E>} 371 * @param filter <EMBED CLASS='external-html' DATA-FTP=E DATA-FILE-ID=PREDICATE_FILTER> 372 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 373 * 374 * @throws NullPointerException if either {@code 'i'} or {@code 'filter'} are passed null 375 */ 376 public ReadOnlyTreeSet 377 (Iterable<E> i, Predicate<? super E> filter, Comparator<? super E> comparator) 378 { 379 fromBuilderOrTreeSet = false; 380 381 final TreeSet<E> treeSet = (comparator != null) 382 ? new TreeSet<>(comparator) 383 : new TreeSet<>(); 384 385 for (E element : i) if (filter.test(element)) treeSet.add(element); 386 387 // Empty Optimization (throw away, completely, the reference, use static-constant) 388 this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet; 389 } 390 391 /** 392 * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents 393 * {@code 'elements'}. 394 * 395 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 396 * 397 * @param elementsType <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_TYPE> 398 * @param filter <EMBED CLASS='external-html' DATA-FTP=E DATA-FILE-ID=PREDICATE_FILTER> 399 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 400 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 401 * 402 * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=CCEX> 403 * 404 * @throws NullPointerException If either {@code 'elementsType'} or {@code 'filter'} are passed 405 * null. 406 */ 407 public ReadOnlyTreeSet( 408 Class<E> elementsType, 409 Predicate<? super E> filter, 410 Comparator<? super E> comparator, 411 Object... elements 412 ) 413 { 414 Objects.requireNonNull(elementsType, ROHelpers.NULL_MSG + "'elementsType'"); 415 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 416 417 fromBuilderOrTreeSet = false; 418 419 final TreeSet<E> treeSet = (comparator != null) 420 ? new TreeSet<>(comparator) 421 : new TreeSet<>(); 422 423 E e; 424 for (Object element : elements) 425 if (filter.test(e = elementsType.cast(element))) 426 treeSet.add(e); 427 428 // Empty Optimization (throw away, completely, the reference, use static-constant) 429 this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet; 430 } 431 432 /** 433 * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents 434 * {@code 'elements'}. 435 * 436 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 437 * 438 * @param mapper <EMBED CLASS='external-html' DATA-FILE-ID=OBJ_E_MAPPER> 439 * @param filter <EMBED CLASS='external-html' DATA-FTP=Object DATA-FILE-ID=PREDICATE_FILTER> 440 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 441 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 442 * 443 * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=CCEX> 444 * @throws NullPointerException If either {@code 'mapper'} or {@code 'filter'} are passed null 445 */ 446 public ReadOnlyTreeSet( 447 Function<Object, ? extends E> mapper, 448 Predicate<Object> filter, 449 Comparator<? super E> comparator, 450 Object... elements 451 ) 452 { 453 Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'"); 454 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 455 456 fromBuilderOrTreeSet = false; 457 458 final TreeSet<E> treeSet = (comparator != null) 459 ? new TreeSet<>(comparator) 460 : new TreeSet<>(); 461 462 for (Object element : elements) 463 if (filter.test(element)) 464 treeSet.add(mapper.apply(element)); 465 466 // Empty Optimization (throw away, completely, the reference, use static-constant) 467 this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet; 468 } 469 470 471 // ******************************************************************************************** 472 // ******************************************************************************************** 473 // @SafeVarargs / Variable-Arity / VarArgs: with Parameterized / Generic Type's 474 // ******************************************************************************************** 475 // ******************************************************************************************** 476 477 478 /** 479 * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents 480 * {@code 'elements'}. 481 * 482 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 483 * 484 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 485 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 486 */ 487 @SafeVarargs 488 public ReadOnlyTreeSet(Comparator<? super E> comparator, E... elements) 489 { 490 fromBuilderOrTreeSet = false; 491 492 if (elements.length == 0) 493 this.treeSet = (TreeSet<E>) EMPTY_TREE_SET; 494 495 else 496 { 497 this.treeSet = (comparator != null) 498 ? new TreeSet<>(comparator) 499 : new TreeSet<>(); 500 501 for (E e : elements) this.treeSet.add(e); 502 } 503 } 504 505 /** 506 * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents 507 * {@code 'elements'}. 508 * 509 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 510 * 511 * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=VARARGS_TYPE_PARAM> 512 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 513 * @param mapper <EMBED CLASS='external-html' DATA-FILE-ID=T_ARR_E_MAPPER> 514 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 515 * 516 * @throws NullPointerException If {@code 'mapper'} is passed null. 517 */ 518 @SafeVarargs 519 public <T> ReadOnlyTreeSet( 520 Comparator<? super E> comparator, 521 Function<? super T, ? extends E> mapper, 522 T... elements 523 ) 524 { 525 Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'"); 526 527 fromBuilderOrTreeSet = false; 528 529 if (elements.length == 0) 530 this.treeSet = (TreeSet<E>) EMPTY_TREE_SET; 531 532 else 533 { 534 this.treeSet = (comparator != null) 535 ? new TreeSet<>(comparator) 536 : new TreeSet<>(); 537 538 for (T t : elements) this.treeSet.add(mapper.apply(t)); 539 } 540 } 541 542 /** 543 * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents 544 * {@code 'elements'}. 545 * 546 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 547 * 548 * @param filter <EMBED CLASS='external-html' DATA-FTP=E DATA-FILE-ID=PREDICATE_FILTER> 549 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 550 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 551 * 552 * @throws NullPointerException If {@code 'filter'} is passed null. 553 */ 554 @SafeVarargs 555 public ReadOnlyTreeSet( 556 Predicate<? super E> filter, 557 Comparator<? super E> comparator, 558 E... elements 559 ) 560 { 561 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 562 563 fromBuilderOrTreeSet = false; 564 565 final TreeSet<E> treeSet = (comparator != null) 566 ? new TreeSet<>(comparator) 567 : new TreeSet<>(); 568 569 for (E e : elements) if (filter.test(e)) treeSet.add(e); 570 571 // Empty Optimization (throw away, completely, the reference, use static-constant) 572 this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet; 573 } 574 575 /** 576 * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents 577 * {@code 'elements'}. 578 * 579 * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN> 580 * 581 * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=VARARGS_TYPE_PARAM> 582 * @param filter <EMBED CLASS='external-html' DATA-FTP=T DATA-FILE-ID=PREDICATE_FILTER> 583 * @param mapper <EMBED CLASS='external-html' DATA-FILE-ID=T_ARR_E_MAPPER> 584 * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR> 585 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 586 * 587 * @throws NullPointerException If either {@code 'mapper'} or {@code 'filter'} are passed null 588 */ 589 @SafeVarargs 590 public <T> ReadOnlyTreeSet( 591 Predicate<? super T> filter, 592 Function<? super T, ? extends E> mapper, 593 Comparator<? super E> comparator, 594 T... elements 595 ) 596 { 597 Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'"); 598 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 599 600 fromBuilderOrTreeSet = false; 601 602 final TreeSet<E> treeSet = (comparator != null) 603 ? new TreeSet<>(comparator) 604 : new TreeSet<>(); 605 606 for (T t : elements) if (filter.test(t)) treeSet.add(mapper.apply(t)); 607 608 // Empty Optimization (throw away, completely, the reference, use static-constant) 609 this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet; 610 } 611 612 613 // ******************************************************************************************** 614 // ******************************************************************************************** 615 // PRIMITIVE-ARRAY INPUT 616 // ******************************************************************************************** 617 // ******************************************************************************************** 618 619 620 /** 621 * Converts a Java Primitive-Array to a {@code ReadOnlyTreeSet<E>}, where {@code 'E'} is the 622 * Java Boxed-Type which corresponds to the Primitive-Array's Type. 623 * 624 * <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CTOR_DESC> 625 * @param primitiveArray <EMBED CLASS='external-html' DATA-FILE-ID=PRIMITIVE_ARRAY> 626 * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CCEX> 627 * @throws NullPointerException If {@code 'primitiveArray'} is passed null; 628 */ 629 @LinkJavaSource(handle="ROHelperPrimitiveArrays", name="buildROListOrSet") 630 public ReadOnlyTreeSet(Object primitiveArray, Comparator<? super E> comparator) 631 { 632 fromBuilderOrTreeSet = false; 633 634 final TreeSet<E> ts = ROHelperPrimitiveArrays.buildROListOrSet( 635 primitiveArray, 636 (int arrayLen) -> (comparator != null) ? new TreeSet<E>(comparator) : new TreeSet<E>(), 637 null 638 ); 639 640 // Empty Optimization (throw away, completely, the reference, use static-constant) 641 this.treeSet = (ts.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : ts; 642 } 643 644 /** 645 * Converts a Java Primitive-Array to a {@code ReadOnlyTreeSet<E>}, where {@code 'E'} is the 646 * Java Boxed-Type which corresponds to the Primitive-Array's Type - <I>but also accepts a 647 * {@code 'filter'} that can remove any array-entries that need to be removed</I>. 648 * 649 * <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CTOR_DESC> 650 * @param primitiveArray <EMBED CLASS='external-html' DATA-FILE-ID=PRIMITIVE_ARRAY> 651 * @param filter <EMBED CLASS='external-html' DATA-FILE-ID=PRED_FILT_PRIM> 652 * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CCEX> 653 * @throws NullPointerException If {@code 'primitiveArray'} is passed null; 654 */ 655 @LinkJavaSource(handle="ROHelperPrimitiveArrays", name="buildROListOrSet") 656 public ReadOnlyTreeSet( 657 Object primitiveArray, 658 Comparator<? super E> comparator, 659 Predicate<?> filter 660 ) 661 { 662 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 663 664 fromBuilderOrTreeSet = false; 665 666 final TreeSet<E> ts = ROHelperPrimitiveArrays.buildROListOrSet( 667 primitiveArray, 668 (int arrayLen) -> (comparator != null) ? new TreeSet<E>(comparator) : new TreeSet<E>(), 669 filter 670 ); 671 672 // Empty Optimization (throw away, completely, the reference, use static-constant) 673 this.treeSet = (ts.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : ts; 674 } 675 676 677 // ******************************************************************************************** 678 // ******************************************************************************************** 679 // java.util.stream.Stream HELPER 680 // ******************************************************************************************** 681 // ******************************************************************************************** 682 683 684 /** 685 * For use with a the Java Stream method {@code 'collect(Collector c)'}. 686 * 687 * <EMBED CLASS='external-html' DATA-ABBREV=ts DATA-FILE-ID=STREAM_COLLECTOR> 688 * 689 * @param <T> This is the Generic-Type of the Input-Stream. It will also be the Generic-Type 690 * of the {@code ReadOnlyTreeSet} that's returned from the stream's {@code collect} method. 691 * 692 * @param characteristics Optional Characteristics List. See Java Stream-API Documentation on 693 * {@code Collector.Characteristics} inner-class for more details. 694 * 695 * @return This returns a collector that may be piped into a stream's {@code 'collect'} method, 696 * as in the example, above. 697 */ 698 public static <T> java.util.stream.Collector 699 <T, ROTreeSetBuilder<T>, ReadOnlyTreeSet<T>> 700 streamCollector(Collector.Characteristics... characteristics) 701 { 702 return Collector.of( 703 ROTreeSetBuilder<T>::new, // The "Supplier" (builds a new ROTreeSetBuilder) 704 ROTreeSetBuilder<T>::add, // The "Accumulator" (adds elements to the builder) 705 706 // Oracle Making Life Difficult - It should be the line below, but, alas, it is not! 707 // ROTreeSetBuilder<T>::addAll, // The "Combiner" (combines multiple ROTreeSetBuilders) 708 // 709 // In Stream.collect(), the 3rd parameter - the "combiner" - is a "BiConsumer<R, R>" 710 // NOTE: A "BiConsumer" is a FunctionalInterface that does not return anything - it is 711 // (obviously) a "void" return method! 712 // 713 // **BUT** 714 // 715 // In Collector.of, the 3rd parameter - the "combiner" - is a "BinaryOperation<R>" 716 717 (ROTreeSetBuilder<T> rotsb1, ROTreeSetBuilder<T> rotsb2) -> 718 { 719 rotsb1.addAll(rotsb2); 720 return rotsb1; 721 }, 722 723 ROTreeSetBuilder<T>::build, // The "Finisher" (Converts Builder to ReadOnlyTreeSet) 724 characteristics 725 ); 726 } 727 728 729 // ******************************************************************************************** 730 // ******************************************************************************************** 731 // Convert to java.util Types 732 // ******************************************************************************************** 733 // ******************************************************************************************** 734 735 736 /** 737 * Clone's {@code 'this'} instance internal {@code TreeSet<E>} field, and returns it. 738 * <EMBED CLASS='external-html' DATA-TYPE=TreeSet DATA-FILE-ID=CLONE_TO> 739 * 740 * @return An independent, mutable copy of {@code 'this'} instance' internal {@code TreeSet<E>} 741 * data-structure. 742 */ 743 public TreeSet<E> cloneToTreeSet() 744 { 745 return fromBuilderOrTreeSet 746 ? new TreeSet<E>(this.treeSet) 747 : (TreeSet<E>) this.treeSet.clone(); 748 } 749 750 /** 751 * <BR>Same: Identical to the method {@link #cloneToTreeSet()}. 752 * <BR>Returns: Has Return-Type {@code Set<E>}, instead. 753 * <BR>Implements: Parent-Class {@link ReadOnlySet#cloneToSet} 754 */ 755 @Torello.JavaDoc.IntoHTMLTable(title="Converts this ReadOnlyTreeSet to a java.util.TreeSet") 756 public Set<E> cloneToSet() { return cloneToTreeSet(); } 757 758 // Documented in the Implemented-Interface ReadOnlySet 759 public Set<E> wrapToImmutableSet() 760 { return Collections.unmodifiableSet(this.treeSet); } 761 762 763 // ******************************************************************************************** 764 // ******************************************************************************************** 765 // Original JDK Methods, java.util.TreeSet 766 // ******************************************************************************************** 767 // ******************************************************************************************** 768 769 770 /** 771 * Returns an iterator over the elements in this set in ascending order. 772 * @return an iterator over the elements in this set in ascending order 773 */ 774 public RemoveUnsupportedIterator<E> iterator() 775 { return new RemoveUnsupportedIterator<>(this.treeSet.iterator()); } 776 777 /** 778 * Returns an iterator over the elements in this set in descending order. 779 * @return an iterator over the elements in this set in descending order 780 */ 781 public RemoveUnsupportedIterator<E> descendingIterator() 782 { return new RemoveUnsupportedIterator<>(this.treeSet.descendingIterator()); } 783 784 @LinkJavaSource(handle="JavaHTMLReadOnlyNavigableSet") 785 public ReadOnlyNavigableSet<E> descendingSet() 786 { 787 return new JavaHTMLReadOnlyNavigableSet<>( 788 fromBuilderOrTreeSet 789 ? ((ROTreeSetBuilder<E>) this.treeSet)._descendingSet(friendClassBadge) 790 : this.treeSet.descendingSet() 791 ); 792 } 793 794 /** 795 * Returns the number of elements in this set (its cardinality). 796 * @return the number of elements in this set (its cardinality) 797 */ 798 public int size() 799 { return this.treeSet.size(); } 800 801 /** 802 * Returns {@code TRUE} if this set contains no elements. 803 * @return {@code TRUE} if this set contains no elements 804 */ 805 public boolean isEmpty() 806 { return this.treeSet.isEmpty(); } 807 808 /** 809 * Returns {@code TRUE} if this set contains the specified element. More formally, returns 810 * {@code TRUE} if and only if this set contains an element {@code e} such that 811 * {@code Objects.equals(o, e)}. 812 * 813 * @param o object to be checked for containment in this set 814 * @return {@code TRUE} if this set contains the specified element 815 * 816 * @throws ClassCastException if the specified object cannot be compared with the elements 817 * currently in the set 818 * 819 * @throws NullPointerException if the specified element is null and this set uses natural 820 * ordering, or its comparator does not permit null elements 821 */ 822 public boolean contains(Object o) 823 { return this.treeSet.contains(o); } 824 825 /** 826 * @throws ClassCastException {@inheritDoc} 827 * 828 * @throws NullPointerException if {@code fromElement} or {@code toElement} is null and this 829 * set uses natural ordering, or its comparator does not permit null elements 830 * 831 * @throws IllegalArgumentException {@inheritDoc} 832 */ 833 @LinkJavaSource(handle="JavaHTMLReadOnlyNavigableSet") 834 public ReadOnlyNavigableSet<E> subSet( 835 E fromElement, boolean fromInclusive, 836 E toElement, boolean toInclusive 837 ) 838 { 839 return new JavaHTMLReadOnlyNavigableSet<>( 840 fromBuilderOrTreeSet 841 ? ((ROTreeSetBuilder<E>) this.treeSet)._subSet 842 (fromElement, fromInclusive, toElement, toInclusive, friendClassBadge) 843 : this.treeSet.subSet(fromElement, fromInclusive, toElement, toInclusive) 844 ); 845 } 846 847 /** 848 * @throws ClassCastException {@inheritDoc} 849 * 850 * @throws NullPointerException if {@code toElement} is null and this set uses natural 851 * ordering, or its comparator does not permit null elements 852 * 853 * @throws IllegalArgumentException {@inheritDoc} 854 */ 855 @LinkJavaSource(handle="JavaHTMLReadOnlyNavigableSet") 856 public ReadOnlyNavigableSet<E> headSet(E toElement, boolean inclusive) 857 { 858 return new JavaHTMLReadOnlyNavigableSet<>( 859 fromBuilderOrTreeSet 860 ? ((ROTreeSetBuilder<E>) this.treeSet)._headSet 861 (toElement, inclusive, friendClassBadge) 862 : this.treeSet.headSet(toElement, inclusive) 863 ); 864 } 865 866 /** 867 * @throws ClassCastException {@inheritDoc} 868 * 869 * @throws NullPointerException if {@code fromElement} is null and this set uses natural 870 * ordering, or its comparator does not permit null elements 871 * 872 * @throws IllegalArgumentException {@inheritDoc} 873 */ 874 @LinkJavaSource(handle="JavaHTMLReadOnlyNavigableSet") 875 public ReadOnlyNavigableSet<E> tailSet(E fromElement, boolean inclusive) 876 { 877 return new JavaHTMLReadOnlyNavigableSet<>( 878 fromBuilderOrTreeSet 879 ? ((ROTreeSetBuilder<E>) this.treeSet)._tailSet 880 (fromElement, inclusive, friendClassBadge) 881 : this.treeSet.tailSet(fromElement, inclusive) 882 ); 883 } 884 885 /** 886 * @throws ClassCastException {@inheritDoc} 887 * 888 * @throws NullPointerException if {@code fromElement} or {@code toElement} is null and this 889 * set uses natural ordering, or its comparator does not permit null elements 890 * 891 * @throws IllegalArgumentException {@inheritDoc} 892 */ 893 @LinkJavaSource(handle="JavaHTMLReadOnlySortedSet") 894 public ReadOnlySortedSet<E> subSet(E fromElement, E toElement) 895 { 896 return new JavaHTMLReadOnlySortedSet<>( 897 fromBuilderOrTreeSet 898 ? ((ROTreeSetBuilder<E>) this.treeSet)._subSet 899 (fromElement, toElement, friendClassBadge) 900 : this.treeSet.subSet(fromElement, toElement) 901 ); 902 } 903 904 /** 905 * @throws ClassCastException {@inheritDoc} 906 * 907 * @throws NullPointerException if {@code toElement} is null and this set uses natural 908 * ordering, or its comparator does not permit null elements 909 * 910 * @throws IllegalArgumentException {@inheritDoc} 911 */ 912 @LinkJavaSource(handle="JavaHTMLReadOnlySortedSet") 913 public ReadOnlySortedSet<E> headSet(E toElement) 914 { 915 return new JavaHTMLReadOnlySortedSet<>( 916 fromBuilderOrTreeSet 917 ? ((ROTreeSetBuilder<E>) this.treeSet)._headSet(toElement, friendClassBadge) 918 : this.treeSet.headSet(toElement) 919 ); 920 } 921 922 /** 923 * @throws ClassCastException {@inheritDoc} 924 * 925 * @throws NullPointerException if {@code fromElement} is null and this set uses natural 926 * ordering, or its comparator does not permit null elements 927 * 928 * @throws IllegalArgumentException {@inheritDoc} 929 */ 930 @LinkJavaSource(handle="JavaHTMLReadOnlySortedSet") 931 public ReadOnlySortedSet<E> tailSet(E fromElement) 932 { 933 return new JavaHTMLReadOnlySortedSet<>( 934 fromBuilderOrTreeSet 935 ? ((ROTreeSetBuilder<E>) this.treeSet)._tailSet(fromElement, friendClassBadge) 936 : this.treeSet.tailSet(fromElement) 937 ); 938 } 939 940 public Comparator<? super E> comparator() 941 { return this.treeSet.comparator(); } 942 943 /** @throws NoSuchElementException {@inheritDoc} */ 944 public E first() 945 { return this.treeSet.first(); } 946 947 /** @throws NoSuchElementException {@inheritDoc} */ 948 public E last() 949 { return this.treeSet.last(); } 950 951 /** 952 * @throws ClassCastException {@inheritDoc} 953 * 954 * @throws NullPointerException if the specified element is null and this set uses natural 955 * ordering, or its comparator does not permit null elements 956 */ 957 public E lower(E e) 958 { return this.treeSet.lower(e); } 959 960 /** 961 * @throws ClassCastException {@inheritDoc} 962 * 963 * @throws NullPointerException if the specified element is null and this set uses natural 964 * ordering, or its comparator does not permit null elements 965 */ 966 public E floor(E e) 967 { return this.treeSet.floor(e); } 968 969 /** 970 * @throws ClassCastException {@inheritDoc} 971 * 972 * @throws NullPointerException if the specified element is null and this set uses natural 973 * ordering, or its comparator does not permit null elements 974 */ 975 public E ceiling(E e) 976 { return this.treeSet.ceiling(e); } 977 978 /** 979 * @throws ClassCastException {@inheritDoc} 980 * 981 * @throws NullPointerException if the specified element is null and this set uses natural 982 * ordering, or its comparator does not permit null elements 983 */ 984 public E higher(E e) 985 { return this.treeSet.higher(e); } 986 987 /** 988 * Utilizes the private, internal {@code java.util.TreeSet} field to generate a 989 * {@code Spliterator}. 990 * 991 * @return a {@code Spliterator} over the elements in this set 992 */ 993 public Spliterator<E> spliterator() 994 { return this.treeSet.spliterator(); } 995 996 997 // ******************************************************************************************** 998 // ******************************************************************************************** 999 // Misc Stuff that is defined in a super-class - for java.util, but not for Java.ReadOnly 1000 // ******************************************************************************************** 1001 // ******************************************************************************************** 1002 1003 1004 public boolean containsAll(Collection<?> c) 1005 { return this.treeSet.containsAll(c); } 1006 1007 public <T> T[] toArray​(T[] a) 1008 { return this.treeSet.toArray(a); } 1009 1010 public Object[] toArray() 1011 { return this.treeSet.toArray(); } 1012 1013 1014 // ******************************************************************************************** 1015 // ******************************************************************************************** 1016 // java.lang.Object 1017 // ******************************************************************************************** 1018 // ******************************************************************************************** 1019 1020 1021 /** 1022 * Returns a {@code String} representation of this {@code TreeSet}. The {@code String} 1023 * representation consists of a list of the collection's elements in the order they are 1024 * returned by its iterator, enclosed in square brackets ({@code "[]"}). Adjacent elements are 1025 * separated by the characters {@code ", "} (comma and space). Elements are converted to 1026 * {@code String's} as by {@code String.valueOf(Object)}. 1027 * 1028 * @return a {@code String} representation of this {@code TreeSet} 1029 */ 1030 public String toString() 1031 { return this.treeSet.toString(); } 1032 1033 /** 1034 * Compares the specified Object with this Set for equality, as per the definition in the 1035 * class {@code java.util.TreeSet}. 1036 * 1037 * @param o object to be compared for equality with this {@code ReadOnlyTreeSet}. 1038 * @return {@code TRUE} if the specified Object is equal to this set 1039 */ 1040 @LinkJavaSource(handle="ROHelperEquals", name="roSetEq") 1041 public boolean equals(Object o) 1042 { return ROHelperEquals.roSetEq(this, o); } 1043 1044 /** 1045 * Returns the hash code value for this Set as per the definition in the class 1046 * {@code java.util.TreeSet}. 1047 */ 1048 public int hashCode() 1049 { return this.treeSet.hashCode(); } 1050} 1051