Java Collections Framework

When a Java program needs to work with a group of related values, an array is often the first data structure beginners learn. Arrays are useful, but their length is fixed after creation. That becomes inconvenient when the number of elements changes during program execution.

Java provides the Collections Framework to make this type of programming easier. It contains interfaces, classes, and utility methods for storing and processing groups of objects. Instead of building common data structures from scratch, a developer can select an existing collection according to the requirements of the program.

For example, an application may need an ordered list of products, a collection containing only unique course codes, a queue of tasks waiting for processing, or a structure that connects student IDs with student names. Different collection types are designed for these different situations.

This tutorial explains the main collection interfaces and several commonly used implementations, with small Java programs that demonstrate how they behave.


What is the Java Collections Framework?

The Java Collections Framework is a standard library architecture for representing and manipulating groups of objects. It provides interfaces such as List, Set, Queue, and Map, together with classes that implement these interfaces.

The important idea is that the interface describes the type of collection behavior, while an implementation provides the actual data structure and operational characteristics.

Simple Example

import java.util.ArrayList;
import java.util.List;

public class CollectionIntro {

    public static void main(String[] args) {

        List<String> subjects = new ArrayList<>();

        subjects.add("Java");
        subjects.add("DBMS");
        subjects.add("Computer Networks");

        System.out.println(subjects);
    }
}

Output

[Java, DBMS, Computer Networks]

Here, List describes the collection behavior and ArrayList provides the implementation. The list can hold multiple values and can grow when new elements are added.


Why Do We Need Collections?

The main purpose of collections is to provide convenient and flexible ways to manage groups of objects. The best collection depends on what the program needs to do with the data.

Consider a student-management application. Student names may need to remain in a particular order, registration numbers must be unique, pending requests may need to be processed one by one, and student records may need to be retrieved using an ID. These requirements do not have the same data structure.

Requirement Suitable Collection
Maintain an ordered group of values List
Prevent duplicate values Set
Process waiting items in sequence Queue
Associate one value with another using a key Map

Collections Framework Hierarchy

The Collections Framework contains several related interfaces. List, Set, and Queue are part of the main collection hierarchy. Map is different because it stores associations between keys and values rather than individual collection elements.

Interface Main Idea Common Implementations
List Ordered elements; duplicates are allowed. ArrayList, LinkedList
Set Unique elements. HashSet, LinkedHashSet, TreeSet
Queue Elements waiting to be processed. LinkedList, PriorityQueue
Map Key-value associations. HashMap, LinkedHashMap, TreeMap

List Interface in Java

A List represents an ordered sequence of elements. A list allows duplicate values, and elements can normally be accessed using their position, called an index.

Lists are useful when the order of elements matters or when a program needs to retrieve an element by its position.

Basic List Example

import java.util.ArrayList;
import java.util.List;

public class ListExample {

    public static void main(String[] args) {

        List<String> chapters = new ArrayList<>();

        chapters.add("Variables");
        chapters.add("Methods");
        chapters.add("Arrays");
        chapters.add("Methods");

        System.out.println(chapters);
        System.out.println(chapters.get(2));
    }
}

Output

[Variables, Methods, Arrays, Methods]
Arrays

The example demonstrates two important properties of a List: the insertion order is retained and the same value can occur more than once.


ArrayList in Java

ArrayList is a resizable-array implementation of the List interface. It is a common choice when a program frequently reads elements by index and does not need constant insertion or removal at arbitrary positions.

Example

import java.util.ArrayList;

public class ArrayListExample {

    public static void main(String[] args) {

        ArrayList<String> courses = new ArrayList<>();

        courses.add("Java");
        courses.add("Python");
        courses.add("SQL");

        System.out.println("Courses: " + courses);

        courses.add("C++");

        System.out.println("After adding: " + courses);

        courses.remove("Python");

        System.out.println("After removal: " + courses);

        System.out.println("Second course: " + courses.get(1));
    }
}

Output

Courses: [Java, Python, SQL]
After adding: [Java, Python, SQL, C++]
After removal: [Java, SQL, C++]
Second course: SQL

Important ArrayList Methods

Method Purpose
add() Adds an element.
get() Retrieves an element using its index.
set() Replaces an element at a particular index.
remove() Removes an element.
contains() Checks whether a value exists.
size() Returns the number of elements.

LinkedList in Java

LinkedList is another implementation of the List interface. It is based on linked nodes, where each node stores an element together with links to other nodes.

LinkedList also implements the Queue and Deque interfaces, which makes it useful when a program needs operations at both ends of a sequence.

Example

import java.util.LinkedList;

public class LinkedListExample {

    public static void main(String[] args) {

        LinkedList<String> tasks = new LinkedList<>();

        tasks.add("Compile Program");
        tasks.add("Run Tests");

        tasks.addFirst("Open Project");

        tasks.addLast("Close Project");

        System.out.println(tasks);
    }
}

Output

[Open Project, Compile Program, Run Tests, Close Project]

The example uses operations at both ends of the list. This is one reason LinkedList can be useful when an application naturally works with the beginning and end of a sequence.


ArrayList vs LinkedList

Feature ArrayList LinkedList
Underlying structure Resizable array Linked nodes
Access by index Efficient Requires traversal
Adding/removing at ends Supported Efficiently supported
Typical use Frequent reading and indexed access Sequence operations involving links or both ends

The choice should be based on the actual access pattern of the application. It is not correct to assume that LinkedList is automatically faster for every insertion or deletion. The position of the operation and the cost of finding that position also matter.


Set Interface in Java

A Set represents a collection in which duplicate elements are not permitted. It is useful when uniqueness is part of the requirement rather than something that must be checked manually.

For example, an application collecting unique course codes can use a Set instead of repeatedly checking whether a code has already been added.


HashSet in Java

HashSet is a commonly used Set implementation. It uses hashing to organize elements and does not guarantee a predictable iteration order.

Example

import java.util.HashSet;

public class HashSetExample {

    public static void main(String[] args) {

        HashSet<String> courseCodes = new HashSet<>();

        courseCodes.add("CS101");
        courseCodes.add("CS205");
        courseCodes.add("CS101");

        System.out.println("Number of unique courses: "
                + courseCodes.size());

        System.out.println(courseCodes);
    }
}

Output

Number of unique courses: 2
[CS101, CS205]

The exact order displayed by a HashSet should not be relied upon. The important property demonstrated here is that adding the same value again does not create another copy.


When Should You Use HashSet?

HashSet is appropriate when uniqueness is more important than maintaining a particular iteration order.

For example, it can be useful for storing unique usernames, distinct subject codes, unique product IDs, or already-processed identifiers.

If the program must preserve insertion order, a different Set implementation such as LinkedHashSet may be more suitable.


Queue Interface in Java

A Queue is designed for elements that are waiting to be processed. A common queue model is FIFO, meaning First In, First Out. The element that enters first is normally processed first.

Queues are useful in task processing, request handling, print scheduling, and other situations where work arrives and is handled in sequence.

Queue Example

import java.util.LinkedList;
import java.util.Queue;

public class QueueExample {

    public static void main(String[] args) {

        Queue<String> tasks = new LinkedList<>();

        tasks.offer("Compile");
        tasks.offer("Test");
        tasks.offer("Deploy");

        System.out.println("Next task: " + tasks.peek());

        String completed = tasks.poll();

        System.out.println("Completed: " + completed);
        System.out.println("Remaining: " + tasks);
    }
}

Output

Next task: Compile
Completed: Compile
Remaining: [Test, Deploy]

Important Queue Methods

Method Purpose
offer() Adds an element to the queue.
peek() Reads the front element without removing it.
poll() Removes and returns the front element.

Map Interface in Java

A Map stores information as key-value pairs. Instead of accessing an item by a numeric index, a program can use a key to find its associated value.

For example, a student ID can act as a key while the student's name can be the corresponding value.


HashMap in Java

HashMap is a widely used Map implementation. Each key can occur only once, while multiple keys may have the same value.

Example

import java.util.HashMap;
import java.util.Map;

public class HashMapExample {

    public static void main(String[] args) {

        Map<Integer, String> students = new HashMap<>();

        students.put(101, "Aman");
        students.put(102, "Neha");
        students.put(103, "Ravi");

        System.out.println("Student 102: "
                + students.get(102));

        System.out.println("All student records:");

        for (Map.Entry<Integer, String> entry
                : students.entrySet()) {

            System.out.println(
                entry.getKey() + " : " + entry.getValue()
            );
        }
    }
}

Output

Student 102: Neha

All student records:
101 : Aman
102 : Neha
103 : Ravi

The put() method creates a key-value association, while get() retrieves the value for a particular key. The entrySet() method provides the entries so that both the key and value can be processed together.

The order shown while iterating through a HashMap should not be treated as guaranteed. If a program needs predictable ordering, another Map implementation may be more appropriate.


What Happens When a HashMap Key Is Repeated?

A Map does not store two separate entries for the same key. If an existing key is used again with a new value, the value associated with that key is replaced.

Example

import java.util.HashMap;

public class DuplicateKeyExample {

    public static void main(String[] args) {

        HashMap<Integer, String> students = new HashMap<>();

        students.put(101, "Aman");

        students.put(101, "Rohit");

        System.out.println(students.get(101));
    }
}

Output

Rohit

The key 101 remains the same, but its associated value changes from Aman to Rohit.


List, Set, Queue and Map Compared

Property List Set Queue Map
Stores Elements Unique elements Elements awaiting processing Key-value pairs
Duplicates Allowed Not allowed Depends on implementation Keys cannot duplicate
Typical access Index Element Front of queue Key
Common implementation ArrayList HashSet LinkedList HashMap

Iterating Through a Collection

A collection can be traversed in several ways. The enhanced for loop is a simple option when the program needs to process each element without manually managing an index.

Example

import java.util.ArrayList;

public class IterationExample {

    public static void main(String[] args) {

        ArrayList<String> topics = new ArrayList<>();

        topics.add("Classes");
        topics.add("Inheritance");
        topics.add("Collections");

        for (String topic : topics) {

            System.out.println("Topic: " + topic);
        }
    }
}

Output

Topic: Classes
Topic: Inheritance
Topic: Collections

Using Generics with Collections

Java collections are commonly used with generics. Generics specify the type of elements that a collection is expected to contain.

Example

ArrayList<Integer> marks = new ArrayList<>();

marks.add(75);
marks.add(82);
marks.add(91);

In this example, the collection is intended to contain Integer values. Generics improve type safety and reduce the need for manual type casting when values are retrieved.


Choosing the Right Collection

There is no single collection that is best for every problem. A useful way to select a collection is to first identify what operation the application performs most often.

Requirement Possible Choice Reason
Ordered data with frequent index access ArrayList Efficient indexed access.
Unique values HashSet Duplicates are not stored.
Key-value lookup HashMap Values can be associated with keys.
Processing items as they arrive Queue Provides queue-oriented operations.
Operations at both ends of a sequence Deque / LinkedList Supports insertion and removal at both ends.

Common Mistakes with Java Collections

1. Assuming Every Collection Preserves Order

Different collection implementations have different ordering characteristics. For example, HashSet and HashMap should not be used when the program depends on a predictable iteration order.

2. Using a List When Uniqueness Is the Requirement

If duplicate values are not meaningful, using a Set may express the requirement more clearly than adding duplicate checks around a List.

3. Choosing LinkedList Automatically for Insertions

Insertion performance depends on where the insertion occurs and whether the required position has already been located. Therefore, LinkedList should not be selected simply because an application performs insertions.

4. Forgetting Generic Types

Using raw collection types removes some of the compile-time type checking provided by generics. Prefer declarations such as List<String> instead of raw List whenever possible.

5. Treating Map Keys Like List Indexes

A Map does not use positional indexes in the same way a List does. A key identifies the associated value, and that key should be chosen according to the application's data model.


Advantages of the Collections Framework


Collections Utility Methods

Java also provides the Collections utility class in the java.util package. It contains methods that can perform common operations on collection objects.

Sorting a List

import java.util.ArrayList;
import java.util.Collections;

public class SortingExample {

    public static void main(String[] args) {

        ArrayList<Integer> marks = new ArrayList<>();

        marks.add(72);
        marks.add(45);
        marks.add(91);
        marks.add(68);

        Collections.sort(marks);

        System.out.println(marks);
    }
}

Output

[45, 68, 72, 91]

The example shows how the utility class can be used to sort a mutable List without implementing a sorting algorithm manually.


Array vs Collection in Java

Array Collection
Length is fixed after creation. Many implementations can grow or shrink dynamically.
Can store primitive values directly. Collections store objects and work with wrapper types for primitives.
Provides basic indexing. Provides many built-in operations through collection APIs.
Useful for fixed-size data. Useful when data management requirements are more flexible.

Real-World Applications of Java Collections

Collections appear throughout Java applications because software frequently works with groups of related information.


How to Select a Collection in an Exam or Project?

A simple decision process can help when choosing a collection.

  1. First determine whether the program needs individual elements or key-value pairs.
  2. If key-value storage is required, consider a Map.
  3. If individual elements are required, decide whether duplicate values are allowed.
  4. If duplicates are allowed and order matters, consider a List.
  5. If duplicates are not allowed, consider a Set.
  6. If elements need to wait for processing, consider a Queue.
  7. Finally, select an implementation according to ordering, access, and update requirements.

Frequently Asked Questions

What is the Java Collections Framework?

It is a group of interfaces, implementations, and utility classes used for storing and processing groups of objects in Java.

What is the difference between List and Set?

A List can contain duplicate elements and represents an ordered sequence, while a Set is designed to contain unique elements.

What is ArrayList?

ArrayList is a resizable-array implementation of the List interface and is commonly used when indexed access is important.

What is HashSet?

HashSet is a Set implementation used when duplicate values should not be stored and a specific iteration order is not required.

What is HashMap?

HashMap is a Map implementation that stores associations between keys and values. Keys are unique within the map.

Can a HashMap contain duplicate keys?

No. If the same key is inserted again, the new value replaces the value previously associated with that key.

What is a Queue?

A Queue is a collection designed for elements that are waiting to be processed. Many queue implementations follow FIFO behavior.

Why are generics used with collections?

Generics specify the expected element type and provide stronger compile-time type checking, making collection code safer and easier to work with.


Java Collections Interview Questions

  1. What is the Java Collections Framework?
  2. What is the difference between Collection and Collections in Java?
  3. What is the difference between List, Set, Queue, and Map?
  4. What is ArrayList and when would you use it?
  5. How is LinkedList different from ArrayList?
  6. Why does a Set not allow duplicate elements?
  7. What is HashSet?
  8. Does HashSet guarantee insertion order?
  9. What is HashMap?
  10. What happens when the same key is inserted twice into a HashMap?
  11. What is the purpose of the Queue interface?
  12. What is the difference between peek() and poll()?
  13. Why are generics important when using collections?
  14. How do you iterate through a Java collection?
  15. How do you decide which collection implementation to use?

Key Points to Remember


Summary

The Java Collections Framework provides a standard way to store and process groups of objects. Instead of relying only on fixed-size arrays, Java programs can use collection interfaces and implementations that match the requirements of the application.

The most important concepts are List, Set, Queue, and Map. ArrayList and LinkedList are commonly used List implementations, HashSet is useful for unique values, Queue is appropriate for processing items in sequence, and HashMap is useful when information needs to be accessed through keys.

The most important lesson is not to memorize one collection as the "best" option. Instead, examine how the data will be stored, accessed, searched, inserted, removed, and ordered, and then choose the collection that fits those requirements.

After understanding collections, the next useful step is learning how Java programs work with files. File handling allows an application to create, read, update, and write information outside the running program.


← Previous: Exception Handling Next: File Handling →

Home Visit Our YouTube Channel