Collections with Generics

Java 14 min min read Updated: Mar 31, 2026 Intermediate
Collections with Generics
Intermediate Topic 9 of 14

Collections with Generics

In real-world Java applications, we often need to store and manage groups of objects such as lists of users, sets of unique values, or key-value mappings. Java provides a powerful framework called the Collections Framework to handle such data efficiently.

Along with collections, Java introduced Generics to provide type safety and avoid runtime errors. Generics ensure that collections store only specific types of objects, making code safer and more readable.

Key Concept: Collections provide data structures to store multiple objects, while Generics ensure type safety by restricting the type of elements stored in those collections.

What is Collection in Java?

A collection is an object that represents a group of elements. Java provides predefined classes and interfaces to manage groups of data dynamically.

Examples:

  • list of students
  • set of unique IDs
  • map of employee ID to employee details

Java Collections Framework

The Java Collections Framework (JCF) is a set of interfaces and classes used to store, manipulate, and process data efficiently.

It mainly includes:

  • Interfaces (List, Set, Map, Queue)
  • Classes (ArrayList, HashSet, HashMap, LinkedList, etc.)
  • Algorithms (sorting, searching, etc.)

Main Collection Interfaces

1. List

  • ordered collection
  • allows duplicate elements
  • supports indexing

2. Set

  • does not allow duplicate elements
  • no indexing

3. Map

  • stores key-value pairs
  • keys must be unique

4. Queue

  • used for processing elements in order (FIFO)

What are Generics?

Generics allow us to define the type of elements a collection can hold. Before generics, collections could store any type of object, which often led to runtime errors.

Without Generics

java import java.util.ArrayList; public class Main { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add("Java"); list.add(100); String s = (String) list.get(1); // Runtime error } }

With Generics

java import java.util.ArrayList; public class Main { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add("Java"); // list.add(100); // Compile-time error String s = list.get(0); System.out.println(s); } }

Generics prevent incorrect data types from being inserted into collections.

Advantages of Generics

  • type safety
  • no need for type casting
  • better readability
  • compile-time error detection

List Interface

The List interface represents an ordered collection of elements that can contain duplicates.

ArrayList Class

ArrayList is one of the most commonly used implementations of the List interface.

Example

java import java.util.ArrayList; public class Main { public static void main(String[] args) { ArrayList list = new ArrayList<>(); list.add("Java"); list.add("Python"); list.add("Java"); System.out.println(list); } }

Output:

text [Java, Python, Java]

Common ArrayList Methods

  • add()
  • get()
  • remove()
  • size()
  • contains()

Example

java list.add("C++"); System.out.println(list.get(1)); System.out.println(list.size());

LinkedList Class

LinkedList is another implementation of List that uses a linked structure instead of an array.

It is efficient for insertion and deletion operations.

Example

java import java.util.LinkedList; LinkedList list = new LinkedList<>(); list.add("Java"); list.add("Python");

Set Interface

The Set interface represents a collection that does not allow duplicate elements.

HashSet Class

HashSet is the most commonly used Set implementation.

Example

java import java.util.HashSet; public class Main { public static void main(String[] args) { HashSet set = new HashSet<>(); set.add("Java"); set.add("Python"); set.add("Java"); System.out.println(set); } }

Output:

text [Java, Python]

Duplicate values are automatically removed.

Map Interface

The Map interface stores data in key-value pairs.

HashMap Class

HashMap is widely used for storing key-value pairs.

Example

java import java.util.HashMap; public class Main { public static void main(String[] args) { HashMap map = new HashMap<>(); map.put(1, "Java"); map.put(2, "Python"); System.out.println(map.get(1)); } }

Iterating Collections

Collections can be traversed using loops.

Using for-each loop

java for (String item : list) { System.out.println(item); }

Using Iterator

java import java.util.Iterator; Iterator it = list.iterator(); while (it.hasNext()) { System.out.println(it.next()); }

Generics with Methods

Generics can also be used with methods.

Example

java public class Main { public static void printData(T data) { System.out.println(data); } public static void main(String[] args) { printData("Java"); printData(100); } }

Bounded Generics

Sometimes we restrict the type of generics using bounds.

Example

java public static void printNumber(T num) { System.out.println(num); }

This method accepts only numeric types.

Wildcards in Generics

Java supports wildcards using ?.

  • ? → unknown type
  • ? extends T → upper bound
  • ? super T → lower bound

Example

java public static void printList(List list) { for (Object obj : list) { System.out.println(obj); } }

Sorting Collections

Collections can be sorted using the Collections utility class.

java import java.util.Collections; Collections.sort(list);

Real-World Example

java import java.util.*; public class Main { public static void main(String[] args) { List marks = new ArrayList<>(); marks.add(85); marks.add(90); marks.add(78); Collections.sort(marks); for (int m : marks) { System.out.println(m); } } }

Common Mistakes

  • not using generics and risking runtime errors
  • confusing List and Set behavior
  • using wrong collection for the use case
  • forgetting that Map keys must be unique
  • incorrect use of wildcards

Best Practices

  • always use generics with collections
  • choose the right collection based on requirement
  • use ArrayList for frequent access
  • use LinkedList for frequent insert/delete
  • use HashSet when uniqueness is required
  • use HashMap for key-value storage

Interview-Oriented Points

  • Collections framework provides data structures
  • Generics ensure type safety
  • List allows duplicates, Set does not
  • Map stores key-value pairs
  • ArrayList is dynamic array
  • HashSet removes duplicates
  • HashMap stores key-value data
  • Generics prevent runtime ClassCastException

Conclusion

Collections and Generics are fundamental parts of Java programming. Collections provide flexible data structures, while Generics ensure type safety and cleaner code.

Mastering collections like List, Set, and Map along with generics is essential for writing efficient and scalable Java applications.

Quick Summary: Collections store groups of objects, and Generics ensure type safety by restricting what type of objects can be stored in those collections.

Get Newsletter

Subscibe to our newsletter and we will notify you about the newest updates on Edugators