Collections
Tags: java, programming, learning, beginners
Published: 2024-07-09 16:39:56

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.

- **Set**s store a group of nonduplicate elements.
- **List**s store an ordered collection of elements.
- **Stack**s store objects that are processed in a last-in, first-out fashion.
- **Queue**s store objects that are processed in a first-in, first-out fashion.
- **PriorityQueue**s 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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q4tlv7r4jeg04p99yumd.png)

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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h9znq2paotlsujpple2n.png)

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.