Previous | Next | Trail Map | Collections | Interfaces

The Collection Interface

A Collection(in the API reference documentation)represents a group of objects, known as its elements. The primary use of the Collection interface is to pass around collections of objects where maximum generality is desired. For example, by convention all general-purpose collection implementations (which typically implement some subinterface of Collection like Set or List) have a constructor that takes a Collection argument. This constructor initializes the new Collection to contain all of the elements in the specified Collection. This constructor allows the caller to create a Collection of a desired implementation type, initially containing all of the elements in any given Collection, whatever its subinterface or implementation type. Suppose you have a Collection, c, which may be a List, a Set, or some other kind of Collection. The following one-liner creates a new ArrayList (an implementation of the List interface), initially containing all of the elements in c:
List l = new ArrayList(c);

The Collection interface is shown below:

public interface Collection {
    // Basic Operations
    int size();
    boolean isEmpty();
    boolean contains(Object element);
    boolean add(Object element);    // Optional
    boolean remove(Object element); // Optional
    Iterator iterator();

    // Bulk Operations
    boolean containsAll(Collection c);
    boolean addAll(Collection c);    // Optional
    boolean removeAll(Collection c); // Optional
    boolean retainAll(Collection c); // Optional
    void clear();                    // Optional        

    // Array Operations
    Object[] toArray();
    Object[] toArray(Object a[]);
}
The interface does about what you'd expect, given that a Collection represents a group of objects. It has methods to tell you how many elements are in the collection (size, isEmpty), to check if a given object is in the collection (contains), to add and remove an element from the collection (add, remove), and to provide an iterator over the collection (iterator).

The add method is defined generally enough so that it makes sense for collections that allow duplicates as well as those that don't. It guarantees that the Collection will contain the specified element after the call completes, and returns true if the Collection changes as a result of the call. Similarly, the remove method is defined to remove a single instance of the specified element from the Collection, assuming the Collection contains the element, and to return true if the Collection was modified as a result.

Iterators

The object returned by the iterator method deserves special mention. It is an Iterator(in the API reference documentation), which is very similar to an Enumeration(in the API reference documentation), but differs in two respects: The first point is important: There was no safe way to remove elements from a collection while traversing it with an Enumeration. The semantics of this operation were ill-defined, and differed from implementation to implementation.

The Iterator interface is shown below:

public interface Iterator {
    boolean hasNext();
    Object next();
    void remove();    // Optional
}
The hasNext method is identical in function to Enumeration.hasMoreElements, and the next method is identical in function to Enumeration.nextElement. The remove method removes from the underlying Collection the last element that was returned by next. The remove method may be called only once per call to next, and throws an exception if this condition is violated. Note that Iterator.remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.

The following snippet shows you how to use an Iterator to filter a Collection, that is, to traverse the collection, removing every element that does not satisfy some condition:

static void filter(Collection c) {
    for (Iterator i = c.iterator(); i.hasNext(); )
        if (!cond(i.next()))
            i.remove();
}
Two things should be kept in mind when looking at this simple piece of code:

Bulk Operations

The bulk operations perform some operation on an entire Collection in a single shot. They are shorthands in the sense that each of them can be simulated, perhaps less efficiently, using the operations described above. The addAll, removeAll, and retainAll methods all return true if the target Collection was modified in the process of executing the operation.

As a simple example of the power of the bulk operations, consider following idiom to remove all instances of a specified element, e from a Collection, c.:

c.removeAll(Collections.singleton(e));
More specifically, suppose that you want to remove all of the null elements from a Collection:
c.removeAll(Collections.singleton(null));
This idiom uses Collections.singleton, which is a static factory method that returns an immutable Set containing only the specified element.

Array Operations

The toArray methods are provided as a bridge between collections and older APIs that expect arrays on input. They allow the contents of a Collection to be translated into an array. The simple form with no arguments creates a new array of Object. The more complex form allows the caller to provide an array or to choose the runtime type of the output array.

For example, suppose c is a Collection The following snippet dumps the contents of c into a newly allocated array of Object whose length is identical to the number of elements in c:

Object[] a = c.toArray();
Suppose c is known to contain only strings. The following snippet dumps the contents of c into a newly allocated array of String whose length is identical to the number of elements in c:
String[] a = (String[]) c.toArray(new String[0]);


Previous | Next | Trail Map | Collections | Contents