001/* 002 * Copyright (c) 1994, 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; 028import Torello.Java.ReadOnly.ROVectorBuilder; 029 030import Torello.JavaDoc.Annotations.LinkJavaSource; 031import Torello.JavaDoc.Annotations.IntoHTMLTable; 032 033import java.io.IOException; 034import java.io.ObjectInputStream; 035import java.io.StreamCorruptedException; 036 037import java.util.*; 038 039import java.util.stream.Collector; 040 041import java.util.function.Consumer; 042import java.util.function.Function; 043import java.util.function.Supplier; 044import java.util.function.Predicate; 045 046/** 047 * Immutable Wrapper for <CODE>java.util.Vector</CODE>, found in the "Java Collections 048 * Framework". 049 * 050 * <EMBED CLASS=globalDefs DATA-JDK=Vector> 051 * <EMBED CLASS='external-html' DATA-FILE-ID=MUCHOS_CONSTRUCTORS> 052 * <EMBED CLASS='external-html' DATA-FILE-ID=DATA_CLASS> 053 * <EMBED CLASS='external-html' DATA-FILE-ID=RO_SYNCHRONIZED> 054 * 055 * @param <E> Type of component elements 056 */ 057@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID="JDHBI_MAIN") 058@SuppressWarnings("unchecked") 059public class ReadOnlyVector<E> 060 // extends AbstractReadOnlyList<E> 061 implements ReadOnlyList<E>, RandomAccess, java.io.Serializable 062{ 063 // ******************************************************************************************** 064 // ******************************************************************************************** 065 // Protected & Private Fields, Methods, Statics 066 // ******************************************************************************************** 067 // ******************************************************************************************** 068 069 070 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 071 protected static final long serialVersionUID = 1; 072 073 // Minor Optimization where new Vector's that have no contents always re-use this static 074 // instance. Since this instance is completely empty, the Raw-Types things is irrelevant. 075 076 @SuppressWarnings("rawtypes") 077 private static final Vector EMPTY_VECTOR = new Vector(0); 078 079 // Singleton & Empty ReadOnlyVector, Uses the "Supplier Constructor" 080 @SuppressWarnings("rawtypes") 081 private static final ReadOnlyVector EMPTY_READONLY_VECTOR = 082 new ReadOnlyVector(0, () -> null); 083 084 // The actual Vector used by this instance. 085 private final Vector<E> vector; 086 087 // TRUE => This was built using the class ROVectorBuilder 088 // FALSE => This was built using the clone() of a standard java.util.Vector constructor 089 090 private final boolean fromBuilderOrVector; 091 092 // Mimics the C++ Keyword/Concept of "Friend Class". Is "Friends With" ROVectorBuilder 093 static class AccessBadge { private AccessBadge() { } } 094 private static final AccessBadge friendClassBadge = new AccessBadge(); 095 096 /** 097 * Returns an empty, <B STYLE='color: red;'>singleton</B>, instance of {@code ReadOnlyVector}. 098 * @param <T> Returned {@link ReadOnlyList}'s Data-Type. 099 * 100 * @return An empty list. Since this list is both empty & read-only, a raw-type singleton 101 * will suffice for all operations offered by this clas. 102 * 103 * <EMBED CLASS='external-html' DATA-FILE-ID=EMPTY_SYNCHRONIZED> 104 */ 105 public static <T> ReadOnlyVector<T> emptyROV() 106 { return (ReadOnlyVector<T>) EMPTY_READONLY_VECTOR; } 107 108 109 // ******************************************************************************************** 110 // ******************************************************************************************** 111 // Basic Constructors 112 // ******************************************************************************************** 113 // ******************************************************************************************** 114 115 116 // To all the readers out there following along: The "AccessBadge" thing is just a slightly 117 // wimpier substitute for the C++ keyword / concept 'friend' or "Friend Class". It means this 118 // constructor is (for all intents and purposes) a private-constructor, except for the class 119 // ROVectorBuilder 120 // 121 // This is the Constructor used by the Builder. It has a "Zero-Size" Optimization 122 123 ReadOnlyVector(ROVectorBuilder<E> rovb, ROVectorBuilder.AccessBadge badge) 124 { 125 Objects.requireNonNull(badge, "Access Badge is null. Requires Friend-Class Badge"); 126 127 this.fromBuilderOrVector = true; 128 this.vector = rovb; 129 } 130 131 /** 132 * Copies parameter {@code 'c'} (and saves it) in order to guarantee that {@code 'this'} 133 * instance is Read-Only, and shielded from outside modification. 134 * 135 * @param c The {@code Collection} to be copied and saved into this instance internal 136 * and private {@code 'vector'} field. 137 */ 138 public ReadOnlyVector(Collection<? extends E> c) 139 { 140 this.fromBuilderOrVector = false; 141 142 // Empty Optimization (throw away, completely, the reference, use static-constant) 143 this.vector = (c.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : new Vector<>(c); 144 } 145 146 /** 147 * Use a {@code Supplier<E>} to provide an arbitrary number of elements of type {@code 'E'} 148 * directly to this constructor. This constructor will request elements from the 149 * {@code Supplier} provided to parameter {@code 's'} until {@code 's'} returns null. 150 * 151 * @param quantityIfKnown If the number of elements to be supplied is known, that number may be 152 * provided so that the internal {@code Vector} is adequately initialized at the beginning 153 * of the constructor, without any need for resizing during construction. 154 * 155 * <BR /><BR />If this parameter is passed null, it will be ignored. When this happens, the 156 * initialization of the internal {@code Vector} will be done by Java's default (Zero 157 * Argument) {@code Vector}-Constructor. 158 * 159 * <BR /><BR />It is not mandatory that the value provided be accurate, as ought be seen in the 160 * code below, this value is solely used for the {@code 'initialCapacity'} parameter to the 161 * {@code Vector} constructor. 162 * 163 * @param s Any Java {@code Supplier<? extends E>} 164 * 165 * @throws IllegalArgumentException if the specified quantity / capacity is negative 166 */ 167 public ReadOnlyVector(Integer quantityIfKnown, Supplier<? extends E> s) 168 { 169 fromBuilderOrVector = false; 170 171 Vector<E>vector = (quantityIfKnown != null) 172 ? new Vector<>(quantityIfKnown) 173 : new Vector<>(); 174 175 E e; 176 while ((e = s.get()) != null) vector.add(e); 177 178 // Empty Optimization (throw away, completely, the reference, use static-constant) 179 this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector; 180 } 181 182 183 // ******************************************************************************************** 184 // ******************************************************************************************** 185 // Iterable & Array Based Constructors - **NO FILTER** 186 // ******************************************************************************************** 187 // ******************************************************************************************** 188 189 190 /** 191 * If only a small amount of processing needs to be done on the contents of some Java 192 * Data-Type, and using an entire Builder-Class seems disproportionately complex - <I>this 193 * constructor can convert any Java {@code Iterable} into a {@code ReadOnlyVector}, using 194 * a simple {@code 'mapper'}</I>. 195 * 196 * <EMBED CLASS=defs DATA-SOURCE=Iterable> 197 * 198 * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_TYPE_PARAM> 199 * @param i Any Java {@code Iterable<T>} 200 * @param mapper <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_MAPPER> 201 * @param sizeIfKnown <EMBED CLASS='external-html' DATA-FILE-ID=VECAL_INIT_CAPACITY> 202 * 203 * @throws NullPointerException If either {@code 'i'} or {@code 'mapper'} are passed null. 204 */ 205 public <T> ReadOnlyVector( 206 Iterable<? extends T> i, 207 Function<? super T, ? extends E> mapper, 208 Integer sizeIfKnown 209 ) 210 { 211 Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'"); 212 213 fromBuilderOrVector = false; 214 215 Vector<E> vector = (sizeIfKnown != null) 216 ? new Vector<>(sizeIfKnown) 217 : new Vector<>(); 218 219 for (T t : i) vector.add(mapper.apply(t)); 220 221 // Empty Optimization (throw away, completely, the reference, use static-constant) 222 this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector; 223 } 224 225 /** 226 * If a Standard Java {@code Iterable} can be directly mapped into a {@code Vector} 227 * (and, ergo, an entire Builder-Instance would be a bit excessive) - <I>this constructor will 228 * seamlessly convert any Java {@code Iterable<E>} directly into a {@code ReadOnlyVector<E>} 229 * with just this single invocation</I>. 230 * 231 * <EMBED CLASS=defs DATA-SOURCE=Iterable> 232 * 233 * @param i Any Java {@code Iteratable<? extends E>} 234 * @param sizeIfKnown <EMBED CLASS='external-html' DATA-FILE-ID=VECAL_INIT_CAPACITY> 235 * 236 * @throws IllegalArgumentException if the specified initial capacity is negative 237 */ 238 public ReadOnlyVector(Iterable<? extends E> i, Integer sizeIfKnown) 239 { 240 fromBuilderOrVector = false; 241 242 Vector<E> vector = (sizeIfKnown != null) 243 ? new Vector<>(sizeIfKnown) 244 : new Vector<>(); 245 246 for (E element : i) vector.add(element); 247 248 // Empty Optimization (throw away, completely, the reference, use static-constant) 249 this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector; 250 } 251 252 /** 253 * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents 254 * {@code 'elements'}. 255 * 256 * @param elementsType <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_TYPE> 257 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 258 * 259 * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=CCEX> 260 * @throws NullPointerException If {@code 'elementsType'} is passed null. 261 */ 262 public ReadOnlyVector(Class<E> elementsType, Object... elements) 263 { 264 Objects.requireNonNull(elementsType, ROHelpers.NULL_MSG + "'elementsType'"); 265 266 fromBuilderOrVector = false; 267 268 if (elements.length == 0) 269 this.vector = (Vector<E>) EMPTY_VECTOR; 270 271 else 272 { 273 this.vector = new Vector<>(elements.length); 274 for (Object element : elements) this.vector.add(elementsType.cast(element)); 275 } 276 } 277 278 /** 279 * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents 280 * {@code 'elements'}. 281 * 282 * @param mapper <EMBED CLASS='external-html' DATA-FILE-ID=OBJ_E_MAPPER> 283 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 284 * 285 * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=CCEX> 286 * @throws NullPointerException If {@code 'mapper'} is passed null. 287 */ 288 public ReadOnlyVector(Function<Object, ? extends E> mapper, Object... elements) 289 { 290 Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'"); 291 292 fromBuilderOrVector = false; 293 294 if (elements.length == 0) 295 this.vector = (Vector<E>) EMPTY_VECTOR; 296 297 else 298 { 299 this.vector = new Vector<>(elements.length); 300 for (Object element : elements) this.vector.add(mapper.apply(element)); 301 } 302 } 303 304 305 // ******************************************************************************************** 306 // ******************************************************************************************** 307 // Iterable & Array Based Constructors - **INCLUDES ELEMENT FILTER** 308 // ******************************************************************************************** 309 // ******************************************************************************************** 310 311 312 /** 313 * If only a small amount of processing needs to be done on the contents of some Java 314 * Data-Type, and using an entire Builder-Class seems disproportionately complex - <I>this 315 * constructor can convert any Java {@code Iterable} into a {@code ReadOnlyVector}, using 316 * a simple {@code 'mapper'}</I>. 317 * 318 * <EMBED CLASS=defs DATA-SOURCE=Iterable> 319 * 320 * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_TYPE_PARAM> 321 * @param i Any Java {@code Iterable<? extends T>} 322 * @param mapper <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_MAPPER> 323 * @param filter <EMBED CLASS='external-html' DATA-FTP=T DATA-FILE-ID=PREDICATE_FILTER> 324 * @param sizeIfKnown <EMBED CLASS='external-html' DATA-FILE-ID=VECAL_INIT_CAPACITY> 325 * 326 * @throws NullPointerException If any of {@code 'i'}, {@code 'mapper'} or {@code 'filter'} are 327 * passed null. 328 */ 329 public <T> ReadOnlyVector( 330 Iterable<? extends T> i, 331 Function<? super T, ? extends E> mapper, 332 Predicate<? super T> filter, 333 Integer sizeIfKnown 334 ) 335 { 336 Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'"); 337 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 338 339 fromBuilderOrVector = false; 340 341 Vector<E> vector = (sizeIfKnown != null) 342 ? new Vector<>(sizeIfKnown) 343 : new Vector<>(); 344 345 for (T t : i) if (filter.test(t)) vector.add(mapper.apply(t)); 346 347 // Empty Optimization (throw away, completely, the reference, use static-constant) 348 this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector; 349 } 350 351 /** 352 * If a Standard Java {@code Iterable} can be directly mapped into an {@code Vector} 353 * (and, ergo, an entire Builder-Instance would be a bit excessive) - <I>this constructor will 354 * seamlessly convert any Java {@code Iterable<E>} directly into a {@code ReadOnlyVector<E>} 355 * with just this single invocation</I>. 356 * 357 * <EMBED CLASS=defs DATA-SOURCE=Iterable> 358 * 359 * @param i Any Java {@code Iteratable<E>} 360 * @param filter <EMBED CLASS='external-html' DATA-FTP=E DATA-FILE-ID=PREDICATE_FILTER> 361 * @param sizeIfKnown <EMBED CLASS='external-html' DATA-FILE-ID=VECAL_INIT_CAPACITY> 362 * 363 * @throws IllegalArgumentException if the specified initial capacity is negative 364 * @throws NullPointerException If either {@code 'i'} or {@code 'filter'} are passed null. 365 */ 366 public ReadOnlyVector( 367 Iterable<? extends E> i, 368 Predicate<? super E> filter, 369 Integer sizeIfKnown 370 ) 371 { 372 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 373 374 fromBuilderOrVector = false; 375 376 Vector<E> vector = (sizeIfKnown != null) 377 ? new Vector<>(sizeIfKnown) 378 : new Vector<>(); 379 380 for (E element : i) if (filter.test(element)) vector.add(element); 381 382 // Empty Optimization (throw away, completely, the reference, use static-constant) 383 this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector; 384 } 385 386 /** 387 * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents 388 * {@code 'elements'}. 389 * 390 * @param elementsType <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_TYPE> 391 * @param filter <EMBED CLASS='external-html' DATA-FTP=E DATA-FILE-ID=PREDICATE_FILTER> 392 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 393 * 394 * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=CCEX> 395 * 396 * @throws NullPointerException If either {@code 'elementsType'} or {@code 'filter'} are passed 397 * null. 398 */ 399 public ReadOnlyVector 400 (Class<E> elementsType, Predicate<? super E> filter, Object... elements) 401 { 402 Objects.requireNonNull(elementsType, ROHelpers.NULL_MSG + "'elementsType'"); 403 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 404 405 fromBuilderOrVector = false; 406 407 Vector<E> vector = new Vector<>(elements.length); 408 409 E e; 410 for (Object element : elements) 411 if (filter.test(e = elementsType.cast(element))) 412 vector.add(e); 413 414 // Empty Optimization (throw away, completely, the reference, use static-constant) 415 this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector; 416 } 417 418 /** 419 * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents 420 * {@code 'elements'}. 421 * 422 * @param mapper <EMBED CLASS='external-html' DATA-FILE-ID=OBJ_E_MAPPER> 423 * @param filter <EMBED CLASS='external-html' DATA-FTP=Object DATA-FILE-ID=PREDICATE_FILTER> 424 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 425 * 426 * @throws NullPointerException If either {@code 'mapper'} or {@code 'filter'} are passed null 427 */ 428 public ReadOnlyVector( 429 Function<Object, ? extends E> mapper, 430 Predicate<Object> filter, 431 Object... elements 432 ) 433 { 434 Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'"); 435 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 436 437 fromBuilderOrVector = false; 438 439 Vector<E> vector = new Vector<>(elements.length); 440 441 for (Object element : elements) 442 if (filter.test(element)) 443 vector.add(mapper.apply(element)); 444 445 // Empty Optimization (throw away, completely, the reference, use static-constant) 446 this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector; 447 } 448 449 450 // ******************************************************************************************** 451 // ******************************************************************************************** 452 // @SafeVarargs / Variable-Arity / VarArgs: with Parameterized / Generic Type's 453 // ******************************************************************************************** 454 // ******************************************************************************************** 455 456 457 /** 458 * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents 459 * {@code 'elements'}. 460 * 461 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 462 */ 463 @SafeVarargs 464 public ReadOnlyVector(E... elements) 465 { 466 fromBuilderOrVector = false; 467 468 if (elements.length == 0) 469 this.vector = (Vector<E>) EMPTY_VECTOR; 470 471 else 472 { 473 this.vector = new Vector<>(elements.length); 474 for (E e : elements) this.vector.add(e); 475 } 476 } 477 478 /** 479 * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents 480 * {@code 'elements'}. 481 * 482 * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=VARARGS_TYPE_PARAM> 483 * @param dummy <EMBED CLASS='external-html' DATA-FILE-ID=DUMMY_INT> 484 * @param mapper <EMBED CLASS='external-html' DATA-FILE-ID=T_ARR_E_MAPPER> 485 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 486 * 487 * @throws NullPointerException If {@code 'mapper'} is null. 488 */ 489 @SafeVarargs 490 public <T> ReadOnlyVector 491 (int dummy, Function<? super T, ? extends E> mapper, T... elements) 492 { 493 Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'"); 494 495 fromBuilderOrVector = false; 496 497 if (elements.length == 0) 498 this.vector = (Vector<E>) EMPTY_VECTOR; 499 500 else 501 { 502 this.vector = new Vector<>(elements.length); 503 for (T t : elements) this.vector.add(mapper.apply(t)); 504 } 505 } 506 507 /** 508 * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents 509 * {@code 'elements'}. 510 * 511 * @param filter <EMBED CLASS='external-html' DATA-FTP=E DATA-FILE-ID=PREDICATE_FILTER> 512 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 513 * 514 * @throws NullPointerException If {@code 'elementsType'} is null. 515 */ 516 @SafeVarargs 517 public ReadOnlyVector(Predicate<? super E> filter, E... elements) 518 { 519 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 520 521 fromBuilderOrVector = false; 522 523 Vector<E> vector = new Vector<>(elements.length); 524 for (E e : elements) if (filter.test(e)) vector.add(e); 525 526 // Empty Optimization (throw away, completely, the reference, use static-constant) 527 this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector; 528 } 529 530 /** 531 * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents 532 * {@code 'elements'}. 533 * 534 * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=VARARGS_TYPE_PARAM> 535 * @param filter <EMBED CLASS='external-html' DATA-FTP=T DATA-FILE-ID=PREDICATE_FILTER> 536 * @param mapper <EMBED CLASS='external-html' DATA-FILE-ID=T_ARR_E_MAPPER> 537 * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS> 538 * 539 * @throws NullPointerException If {@code 'mapper'} or {@code 'filter'} is null. 540 */ 541 @SafeVarargs 542 public <T> ReadOnlyVector( 543 Predicate<? super T> filter, 544 Function<? super T, ? extends E> mapper, 545 T... elements 546 ) 547 { 548 Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'"); 549 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 550 551 fromBuilderOrVector = false; 552 553 Vector<E> vector = new Vector<>(elements.length); 554 for (T t : elements) if (filter.test(t)) vector.add(mapper.apply(t)); 555 556 // Empty Optimization (throw away, completely, the reference, use static-constant) 557 this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector; 558 } 559 560 561 // ******************************************************************************************** 562 // ******************************************************************************************** 563 // PRIMITIVE-ARRAY INPUT 564 // ******************************************************************************************** 565 // ******************************************************************************************** 566 567 568 /** 569 * Converts a Java Primitive-Array to a {@code ReadOnlyVector<E>}, where {@code 'E'} is the 570 * Java Boxed-Type which corresponds to the Primitive-Array's Type. 571 * 572 * <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CTOR_DESC> 573 * @param primitiveArray <EMBED CLASS='external-html' DATA-FILE-ID=PRIMITIVE_ARRAY> 574 * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CCEX> 575 * @throws NullPointerException If {@code 'primitiveArray'} is passed null; 576 */ 577 @LinkJavaSource(handle="ROHelperPrimitiveArrays", name="buildROListOrSet") 578 public ReadOnlyVector(Object primitiveArray) 579 { 580 fromBuilderOrVector = false; 581 582 Vector<E> v = ROHelperPrimitiveArrays.buildROListOrSet( 583 primitiveArray, 584 (int arrayLen) -> new Vector<E>(arrayLen), 585 null 586 ); 587 588 // Empty Optimization (throw away, completely, the reference, use static-constant) 589 this.vector = (v.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : v; 590 } 591 592 /** 593 * Converts a Java Primitive-Array to a {@code ReadOnlyVector<E>}, where {@code 'E'} is the 594 * Java Boxed-Type which corresponds to the Primitive-Array's Type - <I>but also accepts a 595 * {@code 'filter'} that can remove any array-entries that need to be removed</I>. 596 * 597 * 598 * <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CTOR_DESC> 599 * @param primitiveArray <EMBED CLASS='external-html' DATA-FILE-ID=PRIMITIVE_ARRAY> 600 * @param filter <EMBED CLASS='external-html' DATA-FILE-ID=PRED_FILT_PRIM> 601 * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CCEX> 602 * @throws NullPointerException If {@code 'primitiveArray'} is passed null; 603 */ 604 @LinkJavaSource(handle="ROHelperPrimitiveArrays", name="buildROListOrSet") 605 public ReadOnlyVector( 606 Object primitiveArray, 607 Predicate<?> filter 608 ) 609 { 610 Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'"); 611 612 fromBuilderOrVector = false; 613 614 Vector<E> v = ROHelperPrimitiveArrays.buildROListOrSet( 615 primitiveArray, 616 (int arrayLen) -> new Vector<E>(arrayLen), 617 filter 618 ); 619 620 // Empty Optimization (throw away, completely, the reference, use static-constant) 621 this.vector = (v.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : v; 622 } 623 624 625 // ******************************************************************************************** 626 // ******************************************************************************************** 627 // java.util.stream.Stream HELPER 628 // ******************************************************************************************** 629 // ******************************************************************************************** 630 631 632 /** 633 * For use with a the Java Stream method {@code 'collect(Collector c)'}. 634 * 635 * <EMBED CLASS='external-html' DATA-ABBREV=v DATA-FILE-ID=STREAM_COLLECTOR> 636 * 637 * @param <T> This is the Generic-Type of the Input-Stream. It will also be the Generic-Type 638 * of the {@code ReadOnlyVector} that's returned from the stream's {@code collect} method. 639 * 640 * @param characteristics Optional Characteristics List. See Java Stream-API Documentation on 641 * {@code Collector.Characteristics} inner-class for more details. 642 * 643 * @return This returns a collector that may be piped into a stream's {@code 'collect'} method, 644 * as in the example, above. 645 */ 646 public static <T> java.util.stream.Collector 647 <T, ROVectorBuilder<T>, ReadOnlyVector<T>> 648 streamCollector(Collector.Characteristics... characteristics) 649 { 650 return Collector.of( 651 ROVectorBuilder<T>::new, // The "Supplier" (builds a new ROVectorBuilder) 652 ROVectorBuilder<T>::add, // The "Accumulator" (adds elements to the builder) 653 654 // Oracle Making Life Difficult - It should be the line below, but, alas, it is not! 655 // ROVectorBuilder<T>::addAll, // The "Combiner" (combines multiple ROVectorBuilders) 656 // 657 // In Stream.collect(), the 3rd parameter - the "combiner" - is a "BiConsumer<R, R>" 658 // NOTE: A "BiConsumer" is a FunctionalInterface that does not return anything - it is 659 // (obviously) a "void" return method! 660 // 661 // **BUT** 662 // 663 // In Collector.of, the 3rd parameter - the "combiner" - is a "BinaryOperation<R>" 664 665 (ROVectorBuilder<T> rovb1, ROVectorBuilder<T> rovb2) -> 666 { 667 rovb1.addAll(rovb2); 668 return rovb1; 669 }, 670 671 ROVectorBuilder<T>::build, // The "Finisher" (Converts Builder to ReadOnlyVector) 672 characteristics 673 ); 674 } 675 676 677 // ******************************************************************************************** 678 // ******************************************************************************************** 679 // Convert to java.util Types 680 // ******************************************************************************************** 681 // ******************************************************************************************** 682 683 684 /** 685 * Clone's {@code 'this'} instance internal {@code Vector<E>} field, and returns it. 686 * <EMBED CLASS='external-html' DATA-TYPE=Vector DATA-FILE-ID=CLONE_TO> 687 * 688 * @return An independent, mutable copy of {@code 'this'} instance' internal {@code Vector<E>} 689 * data-structure. 690 */ 691 public Vector<E> cloneToVector() 692 { 693 return fromBuilderOrVector 694 ? new Vector<E>(this.vector) 695 : (Vector<E>) this.vector.clone(); 696 } 697 698 /** 699 * <BR>Same: Identical to the method {@link #cloneToVector()}. 700 * <BR>Returns: Has Return-Type {@code List<E>}, instead. 701 * <BR>Implements: Parent-Class {@link ReadOnlyList#cloneToList} 702 */ 703 @IntoHTMLTable(title="Converts this ReadOnlyVector to a java.util.Vector") 704 public List<E> cloneToList() { return cloneToVector(); } 705 706 // Documented in the Implemented-Interface ReadOnlyList 707 public List<E> wrapToImmutableList() 708 { return Collections.unmodifiableList(this.vector); } 709 710 711 // ******************************************************************************************** 712 // ******************************************************************************************** 713 // Original JDK Methods, java.util.Vectpr 714 // ******************************************************************************************** 715 // ******************************************************************************************** 716 717 718 /** 719 * Copies the components of this {@code Vector} into the specified array. The item at 720 * index{@code k} in this {@code Vector} is copied into component {@code k} of {@code anArray}. 721 * 722 * @param anArray the array into which the components get copied 723 * 724 * @throws NullPointerException if the given array is null 725 * 726 * @throws IndexOutOfBoundsException if the specified array is not large enough to hold all the 727 * components of this {@code Vector} 728 * 729 * @throws ArrayStoreException if a component of this {@code Vector} is not of a runtime type 730 * that can be stored in the specified array 731 * 732 * @see #toArray(Object[]) 733 */ 734 public void copyInto(Object[] anArray) 735 { this.vector.copyInto(anArray); } 736 737 /** 738 * Returns the current capacity of this {@code Vector}. 739 * 740 * @return the current capacity (the length of its internal data array, kept in the field 741 * {@code elementData} of this {@code Vector}) 742 */ 743 public int capacity() 744 { return this.vector.capacity(); } 745 746 /** 747 * Returns the number of components in this {@code Vector}. 748 * 749 * @return the number of components in this {@code Vector} 750 */ 751 public int size() 752 { return this.vector.size(); } 753 754 /** 755 * Tests if this {@code Vector} has no components. 756 * 757 * @return {@code TRUE} if and only if this {@code Vector} has no components, that is, its 758 * size is zero; {@code FALSE} otherwise. 759 */ 760 public boolean isEmpty() 761 { return this.vector.isEmpty(); } 762 763 /** 764 * Returns an enumeration of the components of this {@code Vector}. The returned 765 * {@code Enumeration} object will generate all items in this {@code Vector}. The first item 766 * generated is the item at index {@code 0}, then the item at index {@code 1}, and so on. If 767 * the {@code Vector} is structurally modified while enumerating over the elements then the 768 * results of enumerating are undefined. 769 * 770 * @return an enumeration of the components of this {@code Vector} 771 */ 772 public Enumeration<E> elements() 773 { return this.vector.elements(); } 774 775 /** 776 * Returns {@code TRUE} if this {@code Vector} contains the specified element. More formally, 777 * returns {@code TRUE} if and only if this {@code Vector} contains at least one element 778 * {@code e} such that {@code Objects.equals(o, e)}. 779 * 780 * @param o element whose presence in this {@code Vector} is to be tested 781 * 782 * @return {@code TRUE} if this {@code Vector} contains the specified element 783 */ 784 public boolean contains(Object o) 785 { return this.vector.contains(o); } 786 787 /** 788 * Returns the index of the first occurrence of the specified element in this {@code Vector}, 789 * or {@code -1} if this {@code Vector} does not contain the element. More formally, returns 790 * the lowest index {@code i} such that {@code Objects.equals(o, get(i))}, or {@code -1} if 791 * there is no such index. 792 * 793 * @param o element to search for 794 * 795 * @return the index of the first occurrence of the specified element in this {@code Vector}, 796 * or {@code -1} if this {@code Vector} does not contain the element 797 */ 798 public int indexOf(Object o) 799 { return this.vector.indexOf(o); } 800 801 /** 802 * Returns the index of the first occurrence of the specified element in this {@code Vector}, 803 * searching forwards from {@code index}, or returns {@code -1} if the element is not found. 804 * More formally, returns the lowest index {@code i} such that 805 * {@code (i >= index && Objects.equals(o, get(i)))}, or {@code -1} if there is no such index. 806 * 807 * @param o element to search for 808 * 809 * @param index index to start searching from 810 * 811 * @return the index of the first occurrence of the element in this {@code Vector} at position 812 * {@code index} or later in the {@code Vector}; {@code -1} if the element is not found. 813 * 814 * @throws IndexOutOfBoundsException if the specified index is negative 815 */ 816 public int indexOf(Object o, int index) 817 { return this.vector.indexOf(o, index); } 818 819 /** 820 * Returns the index of the last occurrence of the specified element in this {@code Vector}, or 821 * {@code -1} if this {@code Vector} does not contain the element. More formally, returns the 822 * highest index {@code i} such that {@code Objects.equals(o, get(i))}, or {@code -1} if there 823 * is no such index. 824 * 825 * @param o element to search for 826 * 827 * @return the index of the last occurrence of the specified element in this {@code Vector}, or 828 * {@code -1} if this {@code Vector} does not contain the element 829 */ 830 public int lastIndexOf(Object o) 831 { return this.vector.lastIndexOf(o); } 832 833 /** 834 * Returns the index of the last occurrence of the specified element in this {@code Vector}, 835 * searching backwards from {@code index}, or returns {@code -1} if the element is not found. 836 * More formally, returns the highest index {@code i} such that 837 * {@code (i <= index && Objects.equals(o, get(i)))}, or {@code -1} if there is no such index. 838 * 839 * @param o element to search for 840 * 841 * @param index index to start searching backwards from 842 * 843 * @return the index of the last occurrence of the element at position less than or equal to 844 * {@code index} in this {@code Vector}; {@code -1} if the element is not found. 845 * 846 * @throws IndexOutOfBoundsException if the specified index is greater than or equal to the 847 * current size of this {@code Vector} 848 */ 849 public int lastIndexOf(Object o, int index) 850 { return this.vector.lastIndexOf(index); } 851 852 /** 853 * Returns the component at the specified index. 854 * 855 * <BR /><BR />This method is identical in functionality to the {@link #get(int)} 856 * method (which is part of the {@link ReadOnlyList} interface). 857 * 858 * @param index an index into this {@code Vector} 859 * 860 * @return the component at the specified index 861 * 862 * @throws ArrayIndexOutOfBoundsException if the index is out of range 863 * ({@code index < 0 || index >= size()}) 864 */ 865 public E elementAt(int index) 866 { return this.vector.elementAt(index); } 867 868 /** 869 * Returns the first component (the item at index {@code 0}) of this {@code Vector}. 870 * 871 * @return the first component of this {@code Vector} 872 * 873 * @throws NoSuchElementException if this {@code Vector} has no components 874 */ 875 public E firstElement() 876 { return this.vector.firstElement(); } 877 878 /** 879 * Returns the last component of the {@code Vector}. 880 * 881 * @return the last component of the {@code Vector}, i.e., the component at index 882 * {@code size() - 1} 883 * 884 * @throws NoSuchElementException if this {@code Vector} is empty 885 */ 886 public E lastElement() 887 { return this.vector.lastElement(); } 888 889 /** Returns an array containing all of the elements in this {@code Vector} in the correct order. */ 890 public Object[] toArray() 891 { return this.vector.toArray(); } 892 893 /** 894 * Returns an array containing all of the elements in this {@code Vector} in the correct order; 895 * the runtime type of the returned array is that of the specified array. If the 896 * {@code Vector} fits in the specified array, it is returned therein. Otherwise, a new array 897 * is allocated with the runtime type of the specified array and the size of this 898 * {@code Vector}. 899 * 900 * <BR /><BR />If the {@code Vector} fits in the specified array with room to spare (i.e., the 901 * array has more elements than the {@code Vector}), the element in the array immediately 902 * following the end of the {@code Vector} is set to null. (This is useful in determining the 903 * length of the {@code Vector} <em>only</em> if the caller knows that the {@code Vector} does 904 * not contain any null elements.) 905 * 906 * @param <T> type of array elements. The same type as {@code <E>} or a supertype of 907 * {@code <E>}. 908 * 909 * @param a the array into which the elements of the {@code Vector} are to be stored, if it is 910 * big enough; otherwise, a new array of the same runtime type is allocated for this purpose. 911 * 912 * @return an array containing the elements of the {@code Vector} 913 * 914 * @throws ArrayStoreException if the runtime type of a, {@code <T>}, is not a supertype of the 915 * runtime type, {@code <E>}, of every element in this {@code Vector} 916 * 917 * @throws NullPointerException if the given array is null 918 */ 919 public <T> T[] toArray(T[] a) 920 { return this.vector.toArray(a); } 921 922 /** 923 * Returns the element at the specified position in this {@code Vector}. 924 * 925 * @param index index of the element to return 926 * 927 * @return object at the specified index 928 * 929 * @throws ArrayIndexOutOfBoundsException if the index is out of range 930 * ({@code index < 0 || index >= size()}) 931 */ 932 public E get(int index) 933 { return this.vector.get(index); } 934 935 /** 936 * Returns {@code TRUE} if this {@code Vector} contains all of the elements in the specified 937 * Collection 938 * 939 * @param c a collection whose elements will be tested for containment in this {@code Vector} 940 * 941 * @return {@code TRUE} if this {@code Vector} contains all of the elements in the specified 942 * collection 943 * 944 * @throws NullPointerException if the specified collection is null 945 */ 946 public boolean containsAll(Collection<?> c) 947 { return this.vector.containsAll(c); } 948 949 /** 950 * Returns a view of the portion of this List between {@code 'fromIndex'}, inclusive, and 951 * {@code 'toIndex'}, exclusive. (If {@code 'fromIndex'} and {@code 'toIndex'} are equal, the 952 * returned List is empty.) The returned List supports all of the optional 953 * {@code ReadOnlyList} operations supported by this {@code ReadOnlyList}. 954 * 955 * <BR /><BR />This method eliminates the need for explicit range operations (of the sort that 956 * commonly exist for arrays). Any operation that expects a List can be used as a range 957 * operation by operating on a subList view instead of a whole List. Idioms may be constructed 958 * for indexOf and lastIndexOf, and all of the algorithms in the Collections class can be 959 * applied to a subList. 960 * 961 * @param fromIndex low endpoint (inclusive) of the subList 962 * @param toIndex high endpoint (exclusive) of the subList 963 * @return a view of the specified range within this List 964 * 965 * @throws IndexOutOfBoundsException if an endpoint index value is out of range 966 * {@code (fromIndex < 0 || toIndex > size)} 967 * 968 * @throws IllegalArgumentException if the endpoint indices are out of order 969 * {@code (fromIndex > toIndex)} 970 */ 971 @LinkJavaSource(handle="JavaHTMLReadOnlyList") 972 public ReadOnlyList<E> subList(int fromIndex, int toIndex) 973 { 974 // return new ReadOnlyVector<>( 975 return new JavaHTMLReadOnlyList<>( 976 fromBuilderOrVector 977 ? ((ROVectorBuilder<E>) this.vector)._subList(fromIndex, toIndex, friendClassBadge) 978 : this.vector.subList(fromIndex, toIndex) 979 ); 980 } 981 982 /** 983 * Returns a list iterator over the elements in this list (in proper sequence), starting at the 984 * specified position in the list. The specified index indicates the first element that would 985 * be returned by an initial call to {@link ReadOnlyListIterator#next next}. An initial call 986 * to {@link ReadOnlyListIterator#previous previous} would return the element with the 987 * specified index minus one. 988 * 989 * @throws IndexOutOfBoundsException if the index is out of range 990 * {@code (index < 0 || index > size())} 991 */ 992 @LinkJavaSource(handle="JavaHTMLReadOnlyListIterator") 993 public ReadOnlyListIterator<E> listIterator(int index) 994 { 995 return new JavaHTMLReadOnlyListIterator<>( 996 fromBuilderOrVector 997 ? ((ROVectorBuilder<E>) this.vector)._listIterator(index, friendClassBadge) 998 : this.vector.listIterator(index) 999 ); 1000 } 1001 1002 /** 1003 * Returns a list iterator over the elements in this list (in proper sequence). 1004 * @see #listIterator(int) 1005 */ 1006 @LinkJavaSource(handle="JavaHTMLReadOnlyListIterator") 1007 public ReadOnlyListIterator<E> listIterator() 1008 { 1009 return new JavaHTMLReadOnlyListIterator<>( 1010 fromBuilderOrVector 1011 ? ((ROVectorBuilder<E>) this.vector)._listIterator(friendClassBadge) 1012 : this.vector.listIterator() 1013 ); 1014 } 1015 1016 /** 1017 * Returns an iterator over the elements in this list in proper sequence. 1018 * 1019 * @return an iterator over the elements in this list in proper sequence 1020 */ 1021 public RemoveUnsupportedIterator<E> iterator() 1022 { return new RemoveUnsupportedIterator<>(this.vector.iterator()); } 1023 1024 /** @throws NullPointerException {@inheritDoc} */ 1025 @Override 1026 public void forEach(Consumer<? super E> action) 1027 { this.vector.forEach(action); } 1028 1029 /** 1030 * Uses the private and internal {@code 'vector'} field to build a {@code 'Spliterator'} 1031 * @return a {@code Spliterator} over the elements in this list 1032 */ 1033 @Override 1034 public Spliterator<E> spliterator() 1035 { return this.vector.spliterator(); } 1036 1037 1038 // ******************************************************************************************** 1039 // ******************************************************************************************** 1040 // java.lang.Object 1041 // ******************************************************************************************** 1042 // ******************************************************************************************** 1043 1044 1045 /** 1046 * Returns a {@code String} representation of this {@code Vector}. The {@code String} 1047 * representation consists of a list of the collection's elements in the order they are 1048 * returned by its iterator, enclosed in square brackets ({@code "[]"}). Adjacent elements are 1049 * separated by the characters {@code ", "} (comma and space). Elements are converted to 1050 * {@code String's} as by {@code String.valueOf(Object)}. 1051 * 1052 * @return a {@code String} representation of this {@code Vector} 1053 */ 1054 public String toString() 1055 { return this.vector.toString(); } 1056 1057 /** 1058 * Compares the specified Object with this List for equality, as per the definition in the 1059 * class {@code java.util.Vector}. 1060 * 1061 * @param o object to be compared for equality with this {@code ReadOnlyVector}. 1062 * @return {@code TRUE} if the specified Object is equal to this list 1063 */ 1064 @LinkJavaSource(handle="ROHelperEquals", name="roListEq") 1065 public boolean equals(Object o) 1066 { return ROHelperEquals.roListEq(this, o); } 1067 1068 /** 1069 * Returns the hash code value for this List as per the definition in the class 1070 * {@code java.util.Vector}. 1071 */ 1072 public int hashCode() 1073 { return this.vector.hashCode(); } 1074} 1075