Path: blob/master/src/java.base/share/classes/java/util/AbstractCollection.java
41152 views
/*1* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.util;2627import jdk.internal.util.ArraysSupport;2829/**30* This class provides a skeletal implementation of the {@code Collection}31* interface, to minimize the effort required to implement this interface. <p>32*33* To implement an unmodifiable collection, the programmer needs only to34* extend this class and provide implementations for the {@code iterator} and35* {@code size} methods. (The iterator returned by the {@code iterator}36* method must implement {@code hasNext} and {@code next}.)<p>37*38* To implement a modifiable collection, the programmer must additionally39* override this class's {@code add} method (which otherwise throws an40* {@code UnsupportedOperationException}), and the iterator returned by the41* {@code iterator} method must additionally implement its {@code remove}42* method.<p>43*44* The programmer should generally provide a void (no argument) and45* {@code Collection} constructor, as per the recommendation in the46* {@code Collection} interface specification.<p>47*48* The documentation for each non-abstract method in this class describes its49* implementation in detail. Each of these methods may be overridden if50* the collection being implemented admits a more efficient implementation.<p>51*52* This class is a member of the53* <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">54* Java Collections Framework</a>.55*56* @author Josh Bloch57* @author Neal Gafter58* @see Collection59* @since 1.260*/6162public abstract class AbstractCollection<E> implements Collection<E> {63/**64* Sole constructor. (For invocation by subclass constructors, typically65* implicit.)66*/67protected AbstractCollection() {68}6970// Query Operations7172/**73* Returns an iterator over the elements contained in this collection.74*75* @return an iterator over the elements contained in this collection76*/77public abstract Iterator<E> iterator();7879public abstract int size();8081/**82* {@inheritDoc}83*84* @implSpec85* This implementation returns {@code size() == 0}.86*/87public boolean isEmpty() {88return size() == 0;89}9091/**92* {@inheritDoc}93*94* @implSpec95* This implementation iterates over the elements in the collection,96* checking each element in turn for equality with the specified element.97*98* @throws ClassCastException {@inheritDoc}99* @throws NullPointerException {@inheritDoc}100*/101public boolean contains(Object o) {102Iterator<E> it = iterator();103if (o==null) {104while (it.hasNext())105if (it.next()==null)106return true;107} else {108while (it.hasNext())109if (o.equals(it.next()))110return true;111}112return false;113}114115/**116* {@inheritDoc}117*118* @implSpec119* This implementation returns an array containing all the elements120* returned by this collection's iterator, in the same order, stored in121* consecutive elements of the array, starting with index {@code 0}.122* The length of the returned array is equal to the number of elements123* returned by the iterator, even if the size of this collection changes124* during iteration, as might happen if the collection permits125* concurrent modification during iteration. The {@code size} method is126* called only as an optimization hint; the correct result is returned127* even if the iterator returns a different number of elements.128*129* <p>This method is equivalent to:130*131* <pre> {@code132* List<E> list = new ArrayList<E>(size());133* for (E e : this)134* list.add(e);135* return list.toArray();136* }</pre>137*/138public Object[] toArray() {139// Estimate size of array; be prepared to see more or fewer elements140Object[] r = new Object[size()];141Iterator<E> it = iterator();142for (int i = 0; i < r.length; i++) {143if (! it.hasNext()) // fewer elements than expected144return Arrays.copyOf(r, i);145r[i] = it.next();146}147return it.hasNext() ? finishToArray(r, it) : r;148}149150/**151* {@inheritDoc}152*153* @implSpec154* This implementation returns an array containing all the elements155* returned by this collection's iterator in the same order, stored in156* consecutive elements of the array, starting with index {@code 0}.157* If the number of elements returned by the iterator is too large to158* fit into the specified array, then the elements are returned in a159* newly allocated array with length equal to the number of elements160* returned by the iterator, even if the size of this collection161* changes during iteration, as might happen if the collection permits162* concurrent modification during iteration. The {@code size} method is163* called only as an optimization hint; the correct result is returned164* even if the iterator returns a different number of elements.165*166* <p>This method is equivalent to:167*168* <pre> {@code169* List<E> list = new ArrayList<E>(size());170* for (E e : this)171* list.add(e);172* return list.toArray(a);173* }</pre>174*175* @throws ArrayStoreException {@inheritDoc}176* @throws NullPointerException {@inheritDoc}177*/178@SuppressWarnings("unchecked")179public <T> T[] toArray(T[] a) {180// Estimate size of array; be prepared to see more or fewer elements181int size = size();182T[] r = a.length >= size ? a :183(T[])java.lang.reflect.Array184.newInstance(a.getClass().getComponentType(), size);185Iterator<E> it = iterator();186187for (int i = 0; i < r.length; i++) {188if (! it.hasNext()) { // fewer elements than expected189if (a == r) {190r[i] = null; // null-terminate191} else if (a.length < i) {192return Arrays.copyOf(r, i);193} else {194System.arraycopy(r, 0, a, 0, i);195if (a.length > i) {196a[i] = null;197}198}199return a;200}201r[i] = (T)it.next();202}203// more elements than expected204return it.hasNext() ? finishToArray(r, it) : r;205}206207/**208* Reallocates the array being used within toArray when the iterator209* returned more elements than expected, and finishes filling it from210* the iterator.211*212* @param r the array, replete with previously stored elements213* @param it the in-progress iterator over this collection214* @return array containing the elements in the given array, plus any215* further elements returned by the iterator, trimmed to size216*/217@SuppressWarnings("unchecked")218private static <T> T[] finishToArray(T[] r, Iterator<?> it) {219int len = r.length;220int i = len;221while (it.hasNext()) {222if (i == len) {223len = ArraysSupport.newLength(len,2241, /* minimum growth */225(len >> 1) + 1 /* preferred growth */);226r = Arrays.copyOf(r, len);227}228r[i++] = (T)it.next();229}230// trim if overallocated231return (i == len) ? r : Arrays.copyOf(r, i);232}233234// Modification Operations235236/**237* {@inheritDoc}238*239* @implSpec240* This implementation always throws an241* {@code UnsupportedOperationException}.242*243* @throws UnsupportedOperationException {@inheritDoc}244* @throws ClassCastException {@inheritDoc}245* @throws NullPointerException {@inheritDoc}246* @throws IllegalArgumentException {@inheritDoc}247* @throws IllegalStateException {@inheritDoc}248*/249public boolean add(E e) {250throw new UnsupportedOperationException();251}252253/**254* {@inheritDoc}255*256* @implSpec257* This implementation iterates over the collection looking for the258* specified element. If it finds the element, it removes the element259* from the collection using the iterator's remove method.260*261* <p>Note that this implementation throws an262* {@code UnsupportedOperationException} if the iterator returned by this263* collection's iterator method does not implement the {@code remove}264* method and this collection contains the specified object.265*266* @throws UnsupportedOperationException {@inheritDoc}267* @throws ClassCastException {@inheritDoc}268* @throws NullPointerException {@inheritDoc}269*/270public boolean remove(Object o) {271Iterator<E> it = iterator();272if (o==null) {273while (it.hasNext()) {274if (it.next()==null) {275it.remove();276return true;277}278}279} else {280while (it.hasNext()) {281if (o.equals(it.next())) {282it.remove();283return true;284}285}286}287return false;288}289290291// Bulk Operations292293/**294* {@inheritDoc}295*296* @implSpec297* This implementation iterates over the specified collection,298* checking each element returned by the iterator in turn to see299* if it's contained in this collection. If all elements are so300* contained {@code true} is returned, otherwise {@code false}.301*302* @throws ClassCastException {@inheritDoc}303* @throws NullPointerException {@inheritDoc}304* @see #contains(Object)305*/306public boolean containsAll(Collection<?> c) {307for (Object e : c)308if (!contains(e))309return false;310return true;311}312313/**314* {@inheritDoc}315*316* @implSpec317* This implementation iterates over the specified collection, and adds318* each object returned by the iterator to this collection, in turn.319*320* <p>Note that this implementation will throw an321* {@code UnsupportedOperationException} unless {@code add} is322* overridden (assuming the specified collection is non-empty).323*324* @throws UnsupportedOperationException {@inheritDoc}325* @throws ClassCastException {@inheritDoc}326* @throws NullPointerException {@inheritDoc}327* @throws IllegalArgumentException {@inheritDoc}328* @throws IllegalStateException {@inheritDoc}329*330* @see #add(Object)331*/332public boolean addAll(Collection<? extends E> c) {333boolean modified = false;334for (E e : c)335if (add(e))336modified = true;337return modified;338}339340/**341* {@inheritDoc}342*343* @implSpec344* This implementation iterates over this collection, checking each345* element returned by the iterator in turn to see if it's contained346* in the specified collection. If it's so contained, it's removed from347* this collection with the iterator's {@code remove} method.348*349* <p>Note that this implementation will throw an350* {@code UnsupportedOperationException} if the iterator returned by the351* {@code iterator} method does not implement the {@code remove} method352* and this collection contains one or more elements in common with the353* specified collection.354*355* @throws UnsupportedOperationException {@inheritDoc}356* @throws ClassCastException {@inheritDoc}357* @throws NullPointerException {@inheritDoc}358*359* @see #remove(Object)360* @see #contains(Object)361*/362public boolean removeAll(Collection<?> c) {363Objects.requireNonNull(c);364boolean modified = false;365Iterator<?> it = iterator();366while (it.hasNext()) {367if (c.contains(it.next())) {368it.remove();369modified = true;370}371}372return modified;373}374375/**376* {@inheritDoc}377*378* @implSpec379* This implementation iterates over this collection, checking each380* element returned by the iterator in turn to see if it's contained381* in the specified collection. If it's not so contained, it's removed382* from this collection with the iterator's {@code remove} method.383*384* <p>Note that this implementation will throw an385* {@code UnsupportedOperationException} if the iterator returned by the386* {@code iterator} method does not implement the {@code remove} method387* and this collection contains one or more elements not present in the388* specified collection.389*390* @throws UnsupportedOperationException {@inheritDoc}391* @throws ClassCastException {@inheritDoc}392* @throws NullPointerException {@inheritDoc}393*394* @see #remove(Object)395* @see #contains(Object)396*/397public boolean retainAll(Collection<?> c) {398Objects.requireNonNull(c);399boolean modified = false;400Iterator<E> it = iterator();401while (it.hasNext()) {402if (!c.contains(it.next())) {403it.remove();404modified = true;405}406}407return modified;408}409410/**411* {@inheritDoc}412*413* @implSpec414* This implementation iterates over this collection, removing each415* element using the {@code Iterator.remove} operation. Most416* implementations will probably choose to override this method for417* efficiency.418*419* <p>Note that this implementation will throw an420* {@code UnsupportedOperationException} if the iterator returned by this421* collection's {@code iterator} method does not implement the422* {@code remove} method and this collection is non-empty.423*424* @throws UnsupportedOperationException {@inheritDoc}425*/426public void clear() {427Iterator<E> it = iterator();428while (it.hasNext()) {429it.next();430it.remove();431}432}433434435// String conversion436437/**438* Returns a string representation of this collection. The string439* representation consists of a list of the collection's elements in the440* order they are returned by its iterator, enclosed in square brackets441* ({@code "[]"}). Adjacent elements are separated by the characters442* {@code ", "} (comma and space). Elements are converted to strings as443* by {@link String#valueOf(Object)}.444*445* @return a string representation of this collection446*/447public String toString() {448Iterator<E> it = iterator();449if (! it.hasNext())450return "[]";451452StringBuilder sb = new StringBuilder();453sb.append('[');454for (;;) {455E e = it.next();456sb.append(e == this ? "(this Collection)" : e);457if (! it.hasNext())458return sb.append(']').toString();459sb.append(',').append(' ');460}461}462463}464465466