/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.util;
import java.lang.reflect.Array;
/**
* Class {@code AbstractCollection} is an abstract implementation of the {@code
* Collection} interface. A subclass must implement the abstract methods {@code
* iterator()} and {@code size()} to create an immutable collection. To create a
* modifiable collection it's necessary to override the {@code add()} method that
* currently throws an {@code UnsupportedOperationException}.
*
* @since 1.2
*/
public abstract class AbstractCollection<E> implements Collection<E> {
/**
* Constructs a new instance of this AbstractCollection.
*/
protected AbstractCollection() {
}
public boolean add(E object) {
throw new UnsupportedOperationException();
}
/**
* Attempts to add all of the objects contained in {@code collection}
* to the contents of this {@code Collection} (optional). This implementation
* iterates over the given {@code Collection} and calls {@code add} for each
* element. If any of these calls return {@code true}, then {@code true} is
* returned as result of this method call, {@code false} otherwise. If this
* {@code Collection} does not support adding elements, an {@code
* UnsupportedOperationException} is thrown.
* <p>
* If the passed {@code Collection} is changed during the process of adding elements
* to this {@code Collection}, the behavior depends on the behavior of the passed
* {@code Collection}.
*
* @param collection
* the collection of objects.
* @return {@code true} if this {@code Collection} is modified, {@code false}
* otherwise.
* @throws UnsupportedOperationException
* if adding to this {@code Collection} is not supported.
* @throws ClassCastException
* if the class of an object is inappropriate for this
* {@code Collection}.
* @throws IllegalArgumentException
* if an object cannot be added to this {@code Collection}.
* @throws NullPointerException
* if {@code collection} is {@code null}, or if it contains
* {@code null} elements and this {@code Collection} does not support
* such elements.
*/
public boolean addAll(Collection<? extends E> collection) {
boolean result = false;
Iterator<? extends E> it = collection.iterator();
while (it.hasNext()) {
if (add(it.next())) {
result = true;
}
}
return result;
}
/**
* Removes all elements from this {@code Collection}, leaving it empty (optional).
* This implementation iterates over this {@code Collection} and calls the {@code
* remove} method on each element. If the iterator does not support removal
* of elements, an {@code UnsupportedOperationException} is thrown.
* <p>
* Concrete implementations usually can clear a {@code Collection} more efficiently
* and should therefore overwrite this method.
*
* @throws UnsupportedOperationException
* it the iterator does not support removing elements from
* this {@code Collection}
* @see #iterator
* @see #isEmpty
* @see #size
*/
public void clear() {
Iterator<E> it = iterator();
while (it.hasNext()) {
it.next();
it.remove();
}
}
/**
* Tests whether this {@code Collection} contains the specified object. This
* implementation iterates over this {@code Collection} and tests, whether any
* element is equal to the given object. If {@code object != null} then
* {@code object.equals(e)} is called for each element {@code e} returned by
* the iterator until the element is found. If {@code object == null} then
* each element {@code e} returned by the iterator is compared with the test
* {@code e == null}.
*
* @param object
* the object to search for.
* @return {@code true} if object is an element of this {@code Collection}, {@code
* false} otherwise.
* @throws ClassCastException
* if the object to look for isn't of the correct type.
* @throws NullPointerException
* if the object to look for is {@code null} and this
* {@code Collection} doesn't support {@code null} elements.
*/
public boolean contains(Object object) {
Iterator<E> it = iterator();
if (object != null) {
while (it.hasNext()) {
if (object.equals(it.next())) {
return true;
}
}
} else {
while (it.hasNext()) {
if (it.next() == null) {
return true;
}
}
}
return false;
}
/**
* Tests whether this {@code Collection} contains all objects contained in the
* specified {@code Collection}. This implementation iterates over the specified
* {@code Collection}. If one element returned by the iterator is not contained in
* this {@code Collection}, then {@code false} is returned; {@code true} otherwise.
*
* @param collection
* the collection of objects.
* @return {@code true} if all objects in the specified {@code Collection} are
* elements of this {@code Collection}, {@code false} otherwise.
* @throws ClassCastException
* if one or more elements of {@code collection} isn't of the
* correct type.
* @throws NullPointerException
* if {@code collection} contains at least one {@code null}
* element and this {@code Collection} doesn't support {@code null}
* elements.
* @throws NullPointerException
* if {@code collection} is {@code null}.
*/
public boolean containsAll(Collection<?> collection) {
Iterator<?> it = collection.iterator();
while (it.hasNext()) {
if (!contains(it.next())) {
return false;
}
}
return true;
}
/**
* Returns if this {@code Collection} contains no elements. This implementation
* tests, whether {@code size} returns 0.
*
* @return {@code true} if this {@code Collection} has no elements, {@code false}
* otherwise.
*
* @see #size
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* Returns an instance of {@link Iterator} that may be used to access the
* objects contained by this {@code Collection}. The order in which the elements are
* returned by the {@link Iterator} is not defined unless the instance of the
* {@code Collection} has a defined order. In that case, the elements are returned in that order.
* <p>
* In this class this method is declared abstract and has to be implemented
* by concrete {@code Collection} implementations.
*
* @return an iterator for accessing the {@code Collection} contents.
*/
public abstract Iterator<E> iterator();
/**
* Removes one instance of the specified object from this {@code Collection} if one
* is contained (optional). This implementation iterates over this
* {@code Collection} and tests for each element {@code e} returned by the iterator,
* whether {@code e} is equal to the given object. If {@code object != null}
* then this test is performed using {@code object.equals(e)}, otherwise
* using {@code object == null}. If an element equal to the given object is
* found, then the {@code remove} method is called on the iterator and
* {@code true} is returned, {@code false} otherwise. If the iterator does
* not support removing elements, an {@code UnsupportedOperationException}
* is thrown.
*
* @param object
* the object to remove.
* @return {@code true} if this {@code Collection} is modified, {@code false}
* otherwise.
* @throws UnsupportedOperationException
* if removing from this {@code Collection} is not supported.
* @throws ClassCastException
* if the object passed is not of the correct type.
* @throws NullPointerException
* if {@code object} is {@code null} and this {@code Collection}
* doesn't support {@code null} elements.
*/
public boolean remove(Object object) {
Iterator<?> it = iterator();
if (object != null) {
while (it.hasNext()) {
if (object.equals(it.next())) {
it.remove();
return true;
}
}
} else {
while (it.hasNext()) {
if (it.next() == null) {
it.remove();
return true;
}
}
}
return false;
}
/**
* Removes all occurrences in this {@code Collection} of each object in the
* specified {@code Collection} (optional). After this method returns none of the
* elements in the passed {@code Collection} can be found in this {@code Collection}
* anymore.
* <p>
* This implementation iterates over this {@code Collection} and tests for each
* element {@code e} returned by the iterator, whether it is contained in
* the specified {@code Collection}. If this test is positive, then the {@code
* remove} method is called on the iterator. If the iterator does not
* support removing elements, an {@code UnsupportedOperationException} is
* thrown.
*
* @param collection
* the collection of objects to remove.
* @return {@code true} if this {@code Collection} is modified, {@code false}
* otherwise.
* @throws UnsupportedOperationException
* if removing from this {@code Collection} is not supported.
* @throws ClassCastException
* if one or more elements of {@code collection} isn't of the
* correct type.
* @throws NullPointerException
* if {@code collection} contains at least one {@code null}
* element and this {@code Collection} doesn't support {@code null}
* elements.
* @throws NullPointerException
* if {@code collection} is {@code null}.
*/
public boolean removeAll(Collection<?> collection) {
boolean result = false;
Iterator<?> it = iterator();
while (it.hasNext()) {
if (collection.contains(it.next())) {
it.remove();
result = true;
}
}
return result;
}
/**
* Removes all objects from this {@code Collection} that are not also found in the
* {@code Collection} passed (optional). After this method returns this {@code Collection}
* will only contain elements that also can be found in the {@code Collection}
* passed to this method.
* <p>
* This implementation iterates over this {@code Collection} and tests for each
* element {@code e} returned by the iterator, whether it is contained in
* the specified {@code Collection}. If this test is negative, then the {@code
* remove} method is called on the iterator. If the iterator does not
* support removing elements, an {@code UnsupportedOperationException} is
* thrown.
*
* @param collection
* the collection of objects to retain.
* @return {@code true} if this {@code Collection} is modified, {@code false}
* otherwise.
* @throws UnsupportedOperationException
* if removing from this {@code Collection} is not supported.
* @throws ClassCastException
* if one or more elements of {@code collection}
* isn't of the correct type.
* @throws NullPointerException
* if {@code collection} contains at least one
* {@code null} element and this {@code Collection} doesn't support
* {@code null} elements.
* @throws NullPointerException
* if {@code collection} is {@code null}.
*/
public boolean retainAll(Collection<?> collection) {
boolean result = false;
Iterator<?> it = iterator();
while (it.hasNext()) {
if (!collection.contains(it.next())) {
it.remove();
result = true;
}
}
return result;
}
/**
* Returns a count of how many objects this {@code Collection} contains.
* <p>
* In this class this method is declared abstract and has to be implemented
* by concrete {@code Collection} implementations.
*
* @return how many objects this {@code Collection} contains, or {@code Integer.MAX_VALUE}
* if there are more than {@code Integer.MAX_VALUE} elements in this
* {@code Collection}.
*/
public abstract int size();
public Object[] toArray() {
return toArrayList().toArray();
}
public <T> T[] toArray(T[] contents) {
return toArrayList().toArray(contents);
}
@SuppressWarnings("unchecked")
private ArrayList<Object> toArrayList() {
ArrayList<Object> result = new ArrayList<Object>(size());
for (E entry : this) {
result.add(entry);
}
return result;
}
/**
* Returns the string representation of this {@code Collection}. The presentation
* has a specific format. It is enclosed by square brackets ("[]"). Elements
* are separated by ', ' (comma and space).
*
* @return the string representation of this {@code Collection}.
*/
@Override
public String toString() {
if (isEmpty()) {
return "[]";
}
StringBuilder buffer = new StringBuilder(size() * 16);
buffer.append('[');
Iterator<?> it = iterator();
while (it.hasNext()) {
Object next = it.next();
if (next != this) {
buffer.append(next);
} else {
buffer.append("(this Collection)");
}
if (it.hasNext()) {
buffer.append(", ");
}
}
buffer.append(']');
return buffer.toString();
}
}