/*
 * @(#)AbstractCollection.java	1.11 98/09/30
 *
 * Copyright 1997, 1998 by Sun Microsystems, Inc.,
 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Sun Microsystems, Inc. ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Sun.
 */

package java.util;

/**
 * This class provides a skeletal implementation of the Collection
 * interface, to minimize the effort required to implement this interface. 

* * To implement an unmodifiable collection, the programmer needs only to * extend this class and provide implementations for the iterator and * size methods. (The iterator returned by the iterator * method must implement hasNext and next.)

* * To implement a modifiable collection, the programmer must additionally * override this class's add method (which otherwise throws an * UnsupportedOperationException), and the iterator returned by the * iterator method must additionally implement its remove * method.

* * The programmer should generally provide a void (no argument) and * Collection constructor, as per the recommendation in the * Collection interface specification.

* * The documentation for each non-abstract methods 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. * * @author Josh Bloch * @version 1.11 09/30/98 * @see Collection * @since JDK1.2 */ public abstract class AbstractCollection implements Collection { /** * 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 iterator(); /** * Returns the number of elements in this collection. If the collection * contains more than Integer.MAX_VALUE elements, returns * Integer.MAX_VALUE. * * @return the number of elements in this collection. */ public abstract int size(); /** * Returns true if this collection contains no elements.

* * This implementation returns size() == 0. * * @return true if this collection contains no elements. */ public boolean isEmpty() { return size() == 0; } /** * Returns true if this collection contains the specified * element. More formally, returns true if and only if this * collection contains at least one element e such that * (o==null ? e==null : o.equals(e)).

* * This implementation iterates over the elements in the collection, * checking each element in turn for equality with the specified element. * * @param o object to be checked for containment in this collection. * @return true if this collection contains the specified element. */ public boolean contains(Object o) { Iterator e = iterator(); if (o==null) { while (e.hasNext()) if (e.next()==null) return true; } else { while (e.hasNext()) if (o.equals(e.next())) return true; } return false; } /** * Returns an array containing all of the elements in this collection. If * the collection makes any guarantees as to what order its elements are * returned by its iterator, this method must return the elements in the * same order. The returned array will be "safe" in that no references to * it are maintained by the collection. (In other words, this method must * allocate a new array even if the collection is backed by an Array). * The caller is thus free to modify the returned array.

* * This implementation allocates the array to be returned, and iterates * over the elements in the collection, storing each object reference in * the next consecutive element of the array, starting with element 0. * * @return an array containing all of the elements in this collection. */ public Object[] toArray() { Object[] result = new Object[size()]; Iterator e = iterator(); for (int i=0; e.hasNext(); i++) result[i] = e.next(); return result; } /** * Returns an array with a runtime type is that of the specified array and * that contains all of the elements in this collection. If the * collection fits in the specified array, it is returned therein. * Otherwise, a new array is allocated with the runtime type of the * specified array and the size of this collection.

* * If the collection fits in the specified array with room to spare (i.e., * the array has more elements than the collection), the element in the * array immediately following the end of the collection is set to * null. This is useful in determining the length of the * collection only if the caller knows that the collection does * not contain any null elements.)

* * If this collection makes any guarantees as to what order its elements * are returned by its iterator, this method must return the elements in * the same order.

* * This implementation checks if the array is large enough to contain the * collection; if not, it allocates a new array of the correct size and * type (using reflection). Then, it iterates over the collection, * storing each object reference in the next consecutive element of the * array, starting with element 0. If the array is larger than the * collection, a null is stored in the first location after the * end of the collection. * * @param a the array into which the elements of the collection are to * be stored, if it is big enough; otherwise, a new array of the * same runtime type is allocated for this purpose. * @return an array containing the elements of the collection. * * @throws NullPointerException if the specified array is null. * * @throws ArrayStoreException if the runtime type of the specified array * is not a supertype of the runtime type of every element in this * collection. */ public Object[] toArray(Object a[]) { int size = size(); if (a.length < size) a = (Object[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size); Iterator it=iterator(); for (int i=0; i size) a[size] = null; return a; } // Modification Operations /** * Ensures that this collection contains the specified element (optional * operation). Returns true if the collection changed as a * result of the call. (Returns false if this collection does * not permit duplicates and already contains the specified element.) * Collections that support this operation may place limitations on what * elements may be added to the collection. In particular, some * collections will refuse to add null elements, and others will * impose restrictions on the type of elements that may be added. * Collection classes should clearly specify in their documentation any * restrictions on what elements may be added.

* * This implementation always throws an * UnsupportedOperationException. * * @param o element whose presence in this collection is to be ensured. * @return true if the collection changed as a result of the call. * * @throws UnsupportedOperationException if the add method is not * supported by this collection. * * @throws NullPointerException if this collection does not permit * null elements, and the specified element is * null. * * @throws ClassCastException if the class of the specified element * prevents it from being added to this collection. * * @throws IllegalArgumentException if some aspect of this element * prevents it from being added to this collection. */ public boolean add(Object o) { throw new UnsupportedOperationException(); } /** * Removes a single instance of the specified element from this * collection, if it is present (optional operation). More formally, * removes an element e such that (o==null ? e==null : * o.equals(e)), if the collection contains one or more such * elements. Returns true if the collection contained the * specified element (or equivalently, if the collection changed as a * result of the call).

* * 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.

* * Note that this implementation throws an * UnsupportedOperationException if the iterator returned by this * collection's iterator method does not implement the remove * method. * * @param o element to be removed from this collection, if present. * @return true if the collection contained the specified * element. * * @throws UnsupportedOperationException if the remove method is * not supported by this collection. */ public boolean remove(Object o) { Iterator e = iterator(); if (o==null) { while (e.hasNext()) { if (e.next()==null) { e.remove(); return true; } } } else { while (e.hasNext()) { if (o.equals(e.next())) { e.remove(); return true; } } } return false; } // Bulk Operations /** * Returns true if this collection contains all of the elements * in the specified collection.

* * 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 * true is returned, otherwise false. * * @param c collection to be checked for containment in this collection. * @return true if this collection contains all of the elements * in the specified collection. * * @see #contains(Object) */ public boolean containsAll(Collection c) { Iterator e = c.iterator(); while (e.hasNext()) if(!contains(e.next())) return false; return true; } /** * Adds all of the elements in the specified collection to this collection * (optional operation). The behavior of this operation is undefined if * the specified collection is modified while the operation is in * progress. (This implies that the behavior of this call is undefined if * the specified collection is this collection, and this collection is * nonempty.)

* * This implementation iterates over the specified collection, and adds * each object returned by the iterator to this collection, in turn.

* * Note that this implementation will throw an * UnsupportedOperationException unless add is * overridden. * * @param c collection whose elements are to be added to this collection. * @return true if this collection changed as a result of the * call. * @throws UnsupportedOperationException if the addAll method is * not supported by this collection. * * @see #add(Object) */ public boolean addAll(Collection c) { boolean modified = false; Iterator e = c.iterator(); while (e.hasNext()) { if(add(e.next())) modified = true; } return modified; } /** * Removes from this collection all of its elements that are contained in * the specified collection (optional operation).

* * 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 remove method.

* * Note that this implementation will throw an * UnsupportedOperationException if the iterator returned by the * iterator method does not implement the remove method. * * @param c elements to be removed from this collection. * @return true if this collection changed as a result of the * call. * * @throws UnsupportedOperationException removeAll is not supported * by this collection. * * @see #remove(Object) * @see #contains(Object) */ public boolean removeAll(Collection c) { boolean modified = false; Iterator e = iterator(); while (e.hasNext()) { if(c.contains(e.next())) { e.remove(); modified = true; } } return modified; } /** * Retains only the elements in this collection that are contained in the * specified collection (optional operation). In other words, removes * from this collection all of its elements that are not contained in the * specified collection.

* * 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 remove method.

* * Note that this implementation will throw an * UnsupportedOperationException if the iterator returned by the * iterator method does not implement the remove method. * * @return true if this collection changed as a result of the * call. * * @throws UnsupportedOperationException if the retainAll method * is not supported by this collection. * * @see #remove(Object) * @see #contains(Object) */ public boolean retainAll(Collection c) { boolean modified = false; Iterator e = iterator(); while (e.hasNext()) { if(!c.contains(e.next())) { e.remove(); modified = true; } } return modified; } /** * Removes all of the elements from this collection (optional operation). * The collection will be empty after this call returns (unless it throws * an exception).

* * This implementation iterates over this collection, removing each * element using the Iterator.remove operation. Most * implementations will probably choose to override this method for * efficiency.

* * Note that this implementation will throw an * UnsupportedOperationException if the iterator returned by this * collection's iterator method does not implement the * remove method. * * @throws UnsupportedOperationException if the remove method is * not supported by this collection. */ public void clear() { Iterator e = iterator(); while (e.hasNext()) { e.next(); e.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 * ("[]"). Adjacent elements are separated by the characters * ", " (comma and space). Elements are converted to strings as * by String.valueOf(Object).

* * This implementation creates an empty string buffer, appends a left * square bracket, and iterates over the collection appending the string * representation of each element in turn. After appending each element * except the last, the string ", " is appended. Finally a right * bracket is appended. A string is obtained from the string buffer, and * returned. * * @return a string representation of this collection. */ public String toString() { StringBuffer buf = new StringBuffer(); Iterator e = iterator(); buf.append("["); int maxIndex = size() - 1; for (int i = 0; i <= maxIndex; i++) { buf.append(String.valueOf(e.next())); if (i < maxIndex) buf.append(", "); } buf.append("]"); return buf.toString(); } }