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