foreach-ui logo
codeLanguages
account_treeDSA

Quick Actions

quizlock Random Quiz
trending_uplock Progress
  • 1
  • 2
  • 3
  • 4
  • quiz
Java
  • Understand the Collections Framework
  • Learn arrays vs collections
  • Explore main collection interfaces

Introduction to Collections

Arrays work fine when you know exactly how many items you need. But what if you don't? What if you need to add or remove elements frequently? Arrays have a fixed size, which becomes limiting fast.

Java's Collections Framework solves this. It's a set of interfaces and classes for working with groups of objects—dynamically.

What is the Collections Framework?

The Collections Framework provides:

  • Dynamic sizing: Collections can grow and shrink as needed
  • Rich functionality: Built-in methods for searching, sorting, inserting, and removing elements
  • Type safety: Using generics, you can specify what type of objects a collection can hold
  • Performance optimization: Different implementations optimized for different use cases

Think of it as having a Swiss Army knife for data storage instead of just a basic knife.

Arrays vs. Collections: Understanding the Difference

Let's compare arrays with collections to understand when to use each:

Arrays

// Fixed size - must be specified at creation
String[] fruits = new String[3];
fruits[0] = "Apple";
fruits[1] = "Banana";
fruits[2] = "Orange";
// Can't easily add more fruits!

Characteristics:

  • Fixed size once created
  • Can store primitives directly (int, double, etc.)
  • Direct index access is very fast
  • Lower-level, less functionality

Collections

// Dynamic size - can grow as needed
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
fruits.add("Grape");  // Easy to add more!
fruits.remove("Banana");  // Easy to remove!

Characteristics:

  • Dynamic sizing
  • Must store objects (use wrapper classes for primitives)
  • Many built-in methods
  • Higher-level abstraction with rich functionality

The Main Collection Interfaces

The Collections Framework is built around several key interfaces. Let's explore the main ones:

1. Collection (Root Interface)

The parent interface for most collection types. It defines basic operations like:

  • add(E e) - Add an element
  • remove(Object o) - Remove an element
  • size() - Get the number of elements
  • clear() - Remove all elements
  • contains(Object o) - Check if element exists

2. List Interface

Ordered collection that allows duplicates

List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Alice");  // Duplicates allowed
// Order is maintained: [Alice, Bob, Alice]

Use List when:

  • You need to maintain insertion order
  • You want to allow duplicate elements
  • You need to access elements by index
  • Example: A shopping list, a playlist of songs

Common implementations:

  • ArrayList - Best for random access and iteration
  • LinkedList - Best for frequent insertions/deletions

3. Set Interface

Collection that does NOT allow duplicates

Set<String> uniqueNames = new HashSet<>();
uniqueNames.add("Alice");
uniqueNames.add("Bob");
uniqueNames.add("Alice");  // Will not be added again
// Result: [Alice, Bob] (or [Bob, Alice] - order not guaranteed)

Use Set when:

  • You need to ensure uniqueness
  • Order doesn't matter (for HashSet)
  • You want to check membership efficiently
  • Example: A set of unique user IDs, a collection of unique tags

Common implementations:

  • HashSet - Fastest, no ordering
  • TreeSet - Sorted order
  • LinkedHashSet - Maintains insertion order

4. Queue Interface

Collection for holding elements prior to processing

Queue<String> tasks = new LinkedList<>();
tasks.offer("Task 1");
tasks.offer("Task 2");
tasks.offer("Task 3");
String nextTask = tasks.poll();  // Retrieves and removes "Task 1"

Use Queue when:

  • You need FIFO (First-In-First-Out) behavior
  • You're implementing task scheduling
  • Example: Print queue, customer service line

5. Map Interface (Not part of Collection hierarchy)

Stores key-value pairs

Map<String, Integer> ages = new HashMap<>();
ages.put("Alice", 25);
ages.put("Bob", 30);
int aliceAge = ages.get("Alice");  // Returns 25

Use Map when:

  • You need to associate keys with values
  • You want fast lookup by key
  • Example: Dictionary, phone book, configuration settings

Common implementations:

  • HashMap - Fastest, no ordering
  • TreeMap - Sorted by keys
  • LinkedHashMap - Maintains insertion order

Choosing the Right Collection

Here's a quick decision guide:

  1. Need key-value pairs? → Use Map (HashMap, TreeMap)
  2. Need unique elements only? → Use Set (HashSet, TreeSet)
  3. Need to maintain order and allow duplicates? → Use List (ArrayList, LinkedList)
  4. Need FIFO processing? → Use Queue (LinkedList, PriorityQueue)

Generics: Type Safety with Collections

One of the most powerful features of collections is generics. They allow you to specify what type of objects a collection can hold:

// Without generics (old way - not type-safe)
ArrayList list = new ArrayList();
list.add("String");
list.add(123);  // Can mix types - dangerous!

// With generics (modern way - type-safe)
ArrayList<String> stringList = new ArrayList<>();
stringList.add("String");
// stringList.add(123);  // Compile error - much safer!

Benefits of generics:

  • Compile-time type checking - Errors caught early
  • No casting needed - Code is cleaner
  • Better readability - Intent is clear

Common Collection Operations

All collections share some common operations:

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

// Adding elements
items.add("Item1");
items.add("Item2");

// Checking size
int size = items.size();  // Returns 2

// Checking if empty
boolean isEmpty = items.isEmpty();  // Returns false

// Checking if contains
boolean hasItem = items.contains("Item1");  // Returns true

// Removing elements
items.remove("Item1");

// Clearing all elements
items.clear();

Performance Considerations

Different collections have different performance characteristics:

Operation ArrayList LinkedList HashSet HashMap
Add (end) O(1) O(1) O(1) O(1)
Add (middle) O(n) O(1)* N/A N/A
Get by index O(1) O(n) N/A N/A
Contains O(n) O(n) O(1) O(1)
Remove O(n) O(1)* O(1) O(1)

*If you have a reference to the node

Best Practices

  1. Use interfaces for declarations:

    List<String> names = new ArrayList<>();  // Good
    ArrayList<String> names = new ArrayList<>();  // Less flexible
    
  2. Initialize with capacity if you know the size:

    List<String> names = new ArrayList<>(100);  // More efficient
    
  3. Use the most specific collection type:

    • If you need uniqueness, use Set
    • If you need ordering and duplicates, use List
    • If you need key-value mapping, use Map
  4. Consider immutability:

    List<String> readOnlyList = Collections.unmodifiableList(myList);
    

Wrapping Up

The Collections Framework gives you the flexibility to work with groups of objects the way you actually need to—dynamically sized, type-safe, and with tons of built-in functionality. Arrays still have their place for fixed-size primitive collections, but for almost everything else, you'll reach for ArrayList, HashMap, HashSet, and their cousins.

In the next lessons, we'll get hands-on with the most common collections. You'll see how ArrayList makes working with lists dead simple, how HashMap turns lookups into one-liners, and how Sets guarantee uniqueness without you having to write any checking logic.

© 2026 forEach. All rights reserved.

Privacy Policy•Terms of Service