Collections Framework
Collections framework provides a standard set of interfaces and classes to store and process data efficiently. like a well-organized toolkit for handling groups of items, without having to create these data structures from scratch.
java.util
includes one of Java’s most powerful subsystems: the Collections Framework.
The Java Collections Framework is a unified architecture for representing and manipulating collections, which are groups of objects.
All major interfaces like List
, Set
, and Queue
extend from Collection
.
Advantages of the Collections Framework
The framework was designed with the following key goals:
High Performance: Core implementations (e.g., ArrayList, LinkedList, HashSet, TreeMap) are highly optimized for performance. Better than Custom implementations.
Unified Architecture: Collections are designed to operate in a similar, consistent manner, enabling interoperability between different types. All classes share common interfaces, different types of collections can work together seamlessly.
Ease of Extension: The architecture allows easy extension or adaptation for new data structures.
An iterator provides a standard way to traverse elements in a collection. All collections implement the
Iterable
interface, enabling the use of enhancedfor-each
loops.The
Collections
utility class provides algorithms such as sorting, reversing, shuffling, and binary search as static methods that operate on collection objects.
Reduces Programming Effort: It provides powerful, ready-to-use data structures and algorithms, which can be directly used.
Promotes Code Reusability: It establishes a common language for passing collections around, making code easier to understand, maintain, and reuse.
Key Interfaces
The framework is built around a core set of interfaces. Each interface defines a specific type of collection.
1. The Collection
Interface
This is the root interface of the hierarchy. It represents a simple group of objects, known as elements. It defines the most basic methods that all collections share, such as add()
, remove()
, size()
, and contains()
.
The List
, Set
, and Queue
interfaces extend this one.
2. The List
Interface
A List
is an ordered collection that can contain duplicate elements. It's like a standard array but with dynamic sizing. Elements can be accessed by their integer index.
- Common Implementations:
ArrayList
,LinkedList
.
3. The Set
Interface
A Set
is a collection that cannot contain duplicate elements. It models the mathematical concept of a set. There is no concept of order in most Set
implementations.
- Common Implementations:
HashSet
,LinkedHashSet
,TreeSet
.
4. The Queue
Interface
A Queue
is a collection used to hold elements before processing. Queues typically order elements in a First-In, First-Out (FIFO) manner. It's like a line of people waiting for a service.
- Common Implementations:
LinkedList
,PriorityQueue
.
5. The Map
Interface
The Map
interface is unique because it doesn't extend the Collection
interface. Instead of storing single elements, it stores key-value pairs. Each key must be unique, and it's used to retrieve the corresponding value. It's like a dictionary or a phone book.
- Common Implementations:
HashMap
,TreeMap
,LinkedHashMap
.
Interface | Description |
---|---|
Collection | The root interface. Enables to work with group of objects. All other collection interfaces extend this. |
List | An ordered collection (sequence). Allows duplicate elements. |
Set | A collection that contains no duplicate elements. |
SortedSet | A Set that maintains elements in ascending order. |
NavigableSet | Extends SortedSet to support navigation methods for closest-match retrievals. |
Queue | A collection for handling special type of lists typically for removing in FIFO order. (holding elements prior to processing) |
Deque | A double-ended queue that allows insertion and removal from both ends. |
ArrayList
Core Methods from List Interface Include
boolean add(E element)
boolean remove(Object element)
boolean contains(Object element)
int size()
void clear()
boolean isEmpty()
Iterator<E> iterator()
Object[] toArray()
<T> T[] toArray(T[] a)
add(int index, E element)
get(int index)
set(int index, E element)
indexOf(Object element)
remove(Object element)
remove(index)
ArrayList
Operations and Use Cases
Creating an ArrayList
, adding elements, accessing them by index, removing them, and iterating through the list.
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args) {
// An ArrayList of Strings
ArrayList<String> fruits = new ArrayList<>();
// Add elements
fruits.add("Apple"); // Add to the end
fruits.add("Banana");
fruits.add("Mango");
fruits.add(1, "Orange"); // Add at a specific index
System.out.println("Current list: " + fruits);
// Access elements
String secondFruit = fruits.get(1); // Get element at index 1
System.out.println("The second fruit is: "
+ secondFruit);
System.out.println("The list contains 'Apple': "
+ fruits.contains("Apple"));
System.out.println("The size of the list is: "
+ fruits.size());
// Remove elements
fruits.remove("Banana"); // Remove by object value
fruits.remove(0); // Remove by index
System.out.println("List after removals: "
+ fruits);
// Iterate through the list
System.out.println("\n--- Iterating through the list ---");
for (String fruit : fruits) {
System.out.println("- " + fruit);
}
// Clear the entire list
fruits.clear();
System.out.println("\nList after clearing: "
+ fruits);
System.out.println("Is the list empty? "
+ fruits.isEmpty());
}
}
Current list: [Apple, Orange, Banana, Mango]
The second fruit is: Orange
The list contains 'Apple': true
The size of the list is: 4
List after removals: [Orange, Mango]
--- Iterating through the list ---
- Orange
- Mango
List after clearing: []
Is the list empty? true
When to Use an ArrayList
An ArrayList
is internally backed by a standard array. This structure makes it the preferred choice in the following scenarios:
Frequent Random Access: When the primary need is to access elements by their index (e.g.,
list.get(5)
),ArrayList
is extremely fast. This operation takes constant time, or O(1).Stable Data with Few Insertions/Deletions: If the list doesn't change much after it's created,
ArrayList
is ideal.Adding/Removing at the End: Adding or removing elements at the end of the list is generally efficient.
You should avoid ArrayList
when you have many insertions or deletions in the middle of the list. Removing an element from the middle requires shifting all subsequent elements, which is a slow operation (O(n)). In such cases, a LinkedList
is a better choice.
Obtaining an Array from an ArrayList
Standard, type-safe method for converting an ArrayList
into a regular Java array using the toArray(T[] a)
method.
import java.util.*;
class ArrayListToArray {
public static void main(String[] args) {
ArrayList<Integer> al = new ArrayList<Integer>();
// Add elements
al.add(1);
al.add(2);
al.add(3);
al.add(4);
System.out.println("Contents of al: " + al);
System.out.println("Size of al: " + al.size()
+ " " + al.getClass().getName());
// Convert to array
Integer[] ia = new Integer[al.size()];
ia = al.toArray(ia);
System.out.println("Size of al: " + ia.size()
+ " " + ia.getClass().getName());
// Sum array elements
int sum = 0;
for (int i : ia)
sum += i;
System.out.println("Sum is: " + sum);
System.out.println('Array Operation: '
+ ia[0] );
}
}
Contents of al: [1, 2, 3, 4]
size: 4
java.util.ArrayList
java.lang.Integer
Sum is: 10
Array Operation: 1
<T> T[] toArray(T[] array)
Returns an array containing all elements in the collection, using the specified array as the destination. If the array is too small, a new array is created; if it's larger, the element after the last is set tonull
.