| /* | |
| * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| package java.util; | |
| import jdk.internal.util.ArraysSupport; | |
| /** | |
| * This class provides a skeletal implementation of the {@code Collection} | |
| * interface, to minimize the effort required to implement this interface. <p> | |
| * | |
| * To implement an unmodifiable collection, the programmer needs only to | |
| * extend this class and provide implementations for the {@code iterator} and | |
| * {@code size} methods. (The iterator returned by the {@code iterator} | |
| * method must implement {@code hasNext} and {@code next}.)<p> | |
| * | |
| * To implement a modifiable collection, the programmer must additionally | |
| * override this class's {@code add} method (which otherwise throws an | |
| * {@code UnsupportedOperationException}), and the iterator returned by the | |
| * {@code iterator} method must additionally implement its {@code remove} | |
| * method.<p> | |
| * | |
| * The programmer should generally provide a void (no argument) and | |
| * {@code Collection} constructor, as per the recommendation in the | |
| * {@code Collection} interface specification.<p> | |
| * | |
| * The documentation for each non-abstract method in this class describes its | |
| * implementation in detail. Each of these methods may be overridden if | |
| * the collection being implemented admits a more efficient implementation.<p> | |
| * | |
| * This class is a member of the | |
| * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework"> | |
| * Java Collections Framework</a>. | |
| * | |
| * @param <E> the type of elements in this collection | |
| * | |
| * @author Josh Bloch | |
| * @author Neal Gafter | |
| * @see Collection | |
| * @since 1.2 | |
| */ | |
| public abstract class AbstractCollection<E> implements Collection<E> { | |
| /** | |
| * Sole constructor. (For invocation by subclass constructors, typically | |
| * implicit.) | |
| */ | |
| protected AbstractCollection() { | |
| } | |
| // Query Operations | |
| /** | |
| * Returns an iterator over the elements contained in this collection. | |
| * | |
| * @return an iterator over the elements contained in this collection | |
| */ | |
| public abstract Iterator<E> iterator(); | |
| public abstract int size(); | |
| /** | |
| * {@inheritDoc} | |
| * | |
| * @implSpec | |
| * This implementation returns {@code size() == 0}. | |
| */ | |
| public boolean isEmpty() { | |
| return size() == 0; | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * | |
| * @implSpec | |
| * This implementation iterates over the elements in the collection, | |
| * checking each element in turn for equality with the specified element. | |
| * | |
| * @throws ClassCastException {@inheritDoc} | |
| * @throws NullPointerException {@inheritDoc} | |
| */ | |
| public boolean contains(Object o) { | |
| Iterator<E> it = iterator(); | |
| if (o==null) { | |
| while (it.hasNext()) | |
| if (it.next()==null) | |
| return true; | |
| } else { | |
| while (it.hasNext()) | |
| if (o.equals(it.next())) | |
| return true; | |
| } | |
| return false; | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * | |
| * @implSpec | |
| * This implementation returns an array containing all the elements | |
| * returned by this collection's iterator, in the same order, stored in | |
| * consecutive elements of the array, starting with index {@code 0}. | |
| * The length of the returned array is equal to the number of elements | |
| * returned by the iterator, even if the size of this collection changes | |
| * during iteration, as might happen if the collection permits | |
| * concurrent modification during iteration. The {@code size} method is | |
| * called only as an optimization hint; the correct result is returned | |
| * even if the iterator returns a different number of elements. | |
| * | |
| * <p>This method is equivalent to: | |
| * | |
| * <pre> {@code | |
| * List<E> list = new ArrayList<E>(size()); | |
| * for (E e : this) | |
| * list.add(e); | |
| * return list.toArray(); | |
| * }</pre> | |
| */ | |
| public Object[] toArray() { | |
| // Estimate size of array; be prepared to see more or fewer elements | |
| Object[] r = new Object[size()]; | |
| Iterator<E> it = iterator(); | |
| for (int i = 0; i < r.length; i++) { | |
| if (! it.hasNext()) // fewer elements than expected | |
| return Arrays.copyOf(r, i); | |
| r[i] = it.next(); | |
| } | |
| return it.hasNext() ? finishToArray(r, it) : r; | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * | |
| * @implSpec | |
| * This implementation returns an array containing all the elements | |
| * returned by this collection's iterator in the same order, stored in | |
| * consecutive elements of the array, starting with index {@code 0}. | |
| * If the number of elements returned by the iterator is too large to | |
| * fit into the specified array, then the elements are returned in a | |
| * newly allocated array with length equal to the number of elements | |
| * returned by the iterator, even if the size of this collection | |
| * changes during iteration, as might happen if the collection permits | |
| * concurrent modification during iteration. The {@code size} method is | |
| * called only as an optimization hint; the correct result is returned | |
| * even if the iterator returns a different number of elements. | |
| * | |
| * <p>This method is equivalent to: | |
| * | |
| * <pre> {@code | |
| * List<E> list = new ArrayList<E>(size()); | |
| * for (E e : this) | |
| * list.add(e); | |
| * return list.toArray(a); | |
| * }</pre> | |
| * | |
| * @throws ArrayStoreException {@inheritDoc} | |
| * @throws NullPointerException {@inheritDoc} | |
| */ | |
| @SuppressWarnings("unchecked") | |
| public <T> T[] toArray(T[] a) { | |
| // Estimate size of array; be prepared to see more or fewer elements | |
| int size = size(); | |
| T[] r = a.length >= size ? a : | |
| (T[])java.lang.reflect.Array | |
| .newInstance(a.getClass().getComponentType(), size); | |
| Iterator<E> it = iterator(); | |
| for (int i = 0; i < r.length; i++) { | |
| if (! it.hasNext()) { // fewer elements than expected | |
| if (a == r) { | |
| r[i] = null; // null-terminate | |
| } else if (a.length < i) { | |
| return Arrays.copyOf(r, i); | |
| } else { | |
| System.arraycopy(r, 0, a, 0, i); | |
| if (a.length > i) { | |
| a[i] = null; | |
| } | |
| } | |
| return a; | |
| } | |
| r[i] = (T)it.next(); | |
| } | |
| // more elements than expected | |
| return it.hasNext() ? finishToArray(r, it) : r; | |
| } | |
| /** | |
| * Reallocates the array being used within toArray when the iterator | |
| * returned more elements than expected, and finishes filling it from | |
| * the iterator. | |
| * | |
| * @param r the array, replete with previously stored elements | |
| * @param it the in-progress iterator over this collection | |
| * @return array containing the elements in the given array, plus any | |
| * further elements returned by the iterator, trimmed to size | |
| */ | |
| @SuppressWarnings("unchecked") | |
| private static <T> T[] finishToArray(T[] r, Iterator<?> it) { | |
| int len = r.length; | |
| int i = len; | |
| while (it.hasNext()) { | |
| if (i == len) { | |
| len = ArraysSupport.newLength(len, | |
| 1, /* minimum growth */ | |
| (len >> 1) + 1 /* preferred growth */); | |
| r = Arrays.copyOf(r, len); | |
| } | |
| r[i++] = (T)it.next(); | |
| } | |
| // trim if overallocated | |
| return (i == len) ? r : Arrays.copyOf(r, i); | |
| } | |
| // Modification Operations | |
| /** | |
| * {@inheritDoc} | |
| * | |
| * @implSpec | |
| * This implementation always throws an | |
| * {@code UnsupportedOperationException}. | |
| * | |
| * @throws UnsupportedOperationException {@inheritDoc} | |
| * @throws ClassCastException {@inheritDoc} | |
| * @throws NullPointerException {@inheritDoc} | |
| * @throws IllegalArgumentException {@inheritDoc} | |
| * @throws IllegalStateException {@inheritDoc} | |
| */ | |
| public boolean add(E e) { | |
| throw new UnsupportedOperationException(); | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * | |
| * @implSpec | |
| * This implementation iterates over the collection looking for the | |
| * specified element. If it finds the element, it removes the element | |
| * from the collection using the iterator's remove method. | |
| * | |
| * <p>Note that this implementation throws an | |
| * {@code UnsupportedOperationException} if the iterator returned by this | |
| * collection's iterator method does not implement the {@code remove} | |
| * method and this collection contains the specified object. | |
| * | |
| * @throws UnsupportedOperationException {@inheritDoc} | |
| * @throws ClassCastException {@inheritDoc} | |
| * @throws NullPointerException {@inheritDoc} | |
| */ | |
| public boolean remove(Object o) { | |
| Iterator<E> it = iterator(); | |
| if (o==null) { | |
| while (it.hasNext()) { | |
| if (it.next()==null) { | |
| it.remove(); | |
| return true; | |
| } | |
| } | |
| } else { | |
| while (it.hasNext()) { | |
| if (o.equals(it.next())) { | |
| it.remove(); | |
| return true; | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| // Bulk Operations | |
| /** | |
| * {@inheritDoc} | |
| * | |
| * @implSpec | |
| * This implementation iterates over the specified collection, | |
| * checking each element returned by the iterator in turn to see | |
| * if it's contained in this collection. If all elements are so | |
| * contained {@code true} is returned, otherwise {@code false}. | |
| * | |
| * @throws ClassCastException {@inheritDoc} | |
| * @throws NullPointerException {@inheritDoc} | |
| * @see #contains(Object) | |
| */ | |
| public boolean containsAll(Collection<?> c) { | |
| for (Object e : c) | |
| if (!contains(e)) | |
| return false; | |
| return true; | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * | |
| * @implSpec | |
| * This implementation iterates over the specified collection, and adds | |
| * each object returned by the iterator to this collection, in turn. | |
| * | |
| * <p>Note that this implementation will throw an | |
| * {@code UnsupportedOperationException} unless {@code add} is | |
| * overridden (assuming the specified collection is non-empty). | |
| * | |
| * @throws UnsupportedOperationException {@inheritDoc} | |
| * @throws ClassCastException {@inheritDoc} | |
| * @throws NullPointerException {@inheritDoc} | |
| * @throws IllegalArgumentException {@inheritDoc} | |
| * @throws IllegalStateException {@inheritDoc} | |
| * | |
| * @see #add(Object) | |
| */ | |
| public boolean addAll(Collection<? extends E> c) { | |
| boolean modified = false; | |
| for (E e : c) | |
| if (add(e)) | |
| modified = true; | |
| return modified; | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * | |
| * @implSpec | |
| * This implementation iterates over this collection, checking each | |
| * element returned by the iterator in turn to see if it's contained | |
| * in the specified collection. If it's so contained, it's removed from | |
| * this collection with the iterator's {@code remove} method. | |
| * | |
| * <p>Note that this implementation will throw an | |
| * {@code UnsupportedOperationException} if the iterator returned by the | |
| * {@code iterator} method does not implement the {@code remove} method | |
| * and this collection contains one or more elements in common with the | |
| * specified collection. | |
| * | |
| * @throws UnsupportedOperationException {@inheritDoc} | |
| * @throws ClassCastException {@inheritDoc} | |
| * @throws NullPointerException {@inheritDoc} | |
| * | |
| * @see #remove(Object) | |
| * @see #contains(Object) | |
| */ | |
| public boolean removeAll(Collection<?> c) { | |
| Objects.requireNonNull(c); | |
| boolean modified = false; | |
| Iterator<?> it = iterator(); | |
| while (it.hasNext()) { | |
| if (c.contains(it.next())) { | |
| it.remove(); | |
| modified = true; | |
| } | |
| } | |
| return modified; | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * | |
| * @implSpec | |
| * This implementation iterates over this collection, checking each | |
| * element returned by the iterator in turn to see if it's contained | |
| * in the specified collection. If it's not so contained, it's removed | |
| * from this collection with the iterator's {@code remove} method. | |
| * | |
| * <p>Note that this implementation will throw an | |
| * {@code UnsupportedOperationException} if the iterator returned by the | |
| * {@code iterator} method does not implement the {@code remove} method | |
| * and this collection contains one or more elements not present in the | |
| * specified collection. | |
| * | |
| * @throws UnsupportedOperationException {@inheritDoc} | |
| * @throws ClassCastException {@inheritDoc} | |
| * @throws NullPointerException {@inheritDoc} | |
| * | |
| * @see #remove(Object) | |
| * @see #contains(Object) | |
| */ | |
| public boolean retainAll(Collection<?> c) { | |
| Objects.requireNonNull(c); | |
| boolean modified = false; | |
| Iterator<E> it = iterator(); | |
| while (it.hasNext()) { | |
| if (!c.contains(it.next())) { | |
| it.remove(); | |
| modified = true; | |
| } | |
| } | |
| return modified; | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * | |
| * @implSpec | |
| * This implementation iterates over this collection, removing each | |
| * element using the {@code Iterator.remove} operation. Most | |
| * implementations will probably choose to override this method for | |
| * efficiency. | |
| * | |
| * <p>Note that this implementation will throw an | |
| * {@code UnsupportedOperationException} if the iterator returned by this | |
| * collection's {@code iterator} method does not implement the | |
| * {@code remove} method and this collection is non-empty. | |
| * | |
| * @throws UnsupportedOperationException {@inheritDoc} | |
| */ | |
| public void clear() { | |
| Iterator<E> it = iterator(); | |
| while (it.hasNext()) { | |
| it.next(); | |
| it.remove(); | |
| } | |
| } | |
| // String conversion | |
| /** | |
| * Returns a string representation of this collection. The string | |
| * representation consists of a list of the collection's elements in the | |
| * order they are returned by its iterator, enclosed in square brackets | |
| * ({@code "[]"}). Adjacent elements are separated by the characters | |
| * {@code ", "} (comma and space). Elements are converted to strings as | |
| * by {@link String#valueOf(Object)}. | |
| * | |
| * @return a string representation of this collection | |
| */ | |
| public String toString() { | |
| Iterator<E> it = iterator(); | |
| if (! it.hasNext()) | |
| return "[]"; | |
| StringBuilder sb = new StringBuilder(); | |
| sb.append('['); | |
| for (;;) { | |
| E e = it.next(); | |
| sb.append(e == this ? "(this Collection)" : e); | |
| if (! it.hasNext()) | |
| return sb.append(']').toString(); | |
| sb.append(',').append(' '); | |
| } | |
| } | |
| } |