The Collection interface defines the common operations for lists, vectors, stacks, queues, priority queues, and sets.
The Java Collections Framework supports two types of containers:
- One for storing a collection of elements is simply called a collection.
- The other, for storing key/value pairs, is called a map.
Maps are efficient data structures for quickly searching an element using a key. Here are the following collections.
- Sets store a group of nonduplicate elements.
- Lists store an ordered collection of elements.
- Stacks store objects that are processed in a last-in, first-out fashion.
- Queues store objects that are processed in a first-in, first-out fashion.
- PriorityQueues store objects that are processed in the order of their priorities.
The common features of these collections are defined in the interfaces, and implementations are provided in concrete classes, as shown in Figure below.
All the interfaces and classes defined in the Java Collections Framework are grouped in the java.util package.
The design of the Java Collections Framework is an excellent example of using interfaces, abstract classes, and concrete classes. The interfaces define the framework. The abstract classes provide partial implementation. The concrete classes implement the interfaces with concrete data structures. Providing an abstract class that partially implements an interface makes it convenient for the user to write the code. The user can simply define a concrete class that extends the abstract class rather implements all the methods in the interface. The abstract classes such as AbstractCollection are provided for convenience. For this reason, they are called convenience abstract classes.
The Collection interface is the root interface for manipulating a collection of objects. Its public methods are listed in Figure below. The AbstractCollection class provides partial implementation for the Collection interface. It implements all the methods in Collection except the add, size, and iterator methods. These are implemented in appropriate concrete subclasses.
The Collection interface provides the basic operations for adding and removing elements in a collection. The add method adds an element to the collection. The addAll method adds all the elements in the specified collection to this collection. The remove method removes an element from the collection. The removeAll method removes the elements from this collection that are present in the specified collection. The retainAll method retains the elements in this collection that are also present in the specified collection. All these methods return boolean. The return value is true if the collection is changed as a result of the method execution. The clear() method simply removes all the elements from the collection.
The methods addAll, removeAll, and retainAll are similar to the set union, difference, and intersection operations.
The Collection interface provides various query operations. The size method returns the number of elements in the collection. The contains method checks whether the collection contains the specified element. The containsAll method checks whether the collection contains all the elements in the specified collection. The isEmpty method returns true if the collection is empty.
The Collection interface provides the toArray() method, which returns an array representation for the collection.
Some of the methods in the Collection interface cannot be implemented in the concrete subclass. In this case, the method would throw java.lang.UnsupportedOperationException, a subclass of RuntimeException. This is a good design that you can use in your project. If a method has no meaning in the subclass, you can implement it as follows:
public void someMethod() {
throw new UnsupportedOperationException
("Method not supported");
}
The code below gives an example to use the methods defined in the Collection interface.
package demo;
import java.util.*; public class TestCollection { public static void main(String[] args) { ArrayList<String> collection1 = new ArrayList<>(); collection1.add("New York"); collection1.add("Atlanta"); collection1.add("Dallas"); collection1.add("Madison"); System.out.println("A list of cities in collection1:"); System.out.println(collection1); System.out.println("\nIs Dallas in collection1? " + collection1.contains("Dallas")); collection1.remove("Dallas"); System.out.println("\n" + collection1.size() + " cities are in collection1 now"); Collection<String> collection2 = new ArrayList<>(); collection2.add("Seattle"); collection2.add("Portland"); collection2.add("Los Angeles"); collection2.add("Atlanta"); System.out.println("\nA list of cities in collection2:"); System.out.println(collection2); ArrayList<String> c1 = (ArrayList<String>)(collection1.clone()); c1.addAll(collection2); System.out.println("\nCities in collection1 or collection2: "); System.out.println(c1); c1 = (ArrayList<String>)(collection1.clone()); c1.retainAll(collection2); System.out.print("\nCities in collection1 and collection2: "); System.out.println(c1); c1 = (ArrayList<String>)(collection1.clone()); c1.removeAll(collection2); System.out.print("\nCities in collection1, but not in 2: "); System.out.println(c1); } }
A list of cities in collection1:
[New York, Atlanta, Dallas, Madison]
Is Dallas in collection1? true
3 cities are in collection1 now
A list of cities in collection2:
[Seattle, Portland, Los Angeles, Atlanta]
Cities in collection1 or collection2:
[New York, Atlanta, Madison, Seattle, Portland, Los Angeles, Atlanta]
Cities in collection1 and collection2: [Atlanta]
Cities in collection1, but not in 2: [New York, Madison]
The program creates a concrete collection object using ArrayList (line 7), and invokes the Collection interface’s contains method (line 16), remove method (line 18), size method (line 19), addAll method (line 31), retainAll method (line 36), and removeAll method (line 41).
For this example, we use ArrayList. You can use any concrete class of Collection such as HashSet, LinkedList, Vector, and Stack to replace ArrayList to test these methods defined in the Collection interface.
The program creates a copy of an array list (lines 30, 35, 40). The purpose of this is to keep the original array list intact and use its copy to perform addAll, retainAll, and removeAll operations.
All the concrete classes in the Java Collections Framework implement the java.lang.Cloneable and java.io.Serializable interfaces except that java.util.PriorityQueue does not implement the Cloneable interface. Thus, all instances of Cloneable except priority queues can be cloned and all instances of Cloneable can be serialized.