Home/Learn/Java A–Z/Collections Utility Methods

Collections Utility Methods

Intermediate
Streams & Functional Java

Master the Collections utility class — sorting, searching, shuffling, frequency, min/max, unmodifiable and synchronized wrappers.

Overview

The java.util.Collections class (note the plural) is a utility class with static methods that operate on Collection instances — analogous to Arrays for arrays. It covers sorting, searching, shuffling, rotating, reversing, frequency counting, finding extremes, and creating unmodifiable or thread-safe wrapper views. Knowing these methods saves you from reimplementing common operations and communicates intent clearly.

Sorting, Searching & Reordering

Collections.sort(list) — stable TimSort, O(n log n); requires Comparable elements Collections.sort(list, comparator) — custom order Collections.binarySearch(sortedList, key) — O(log n); list must be sorted first Collections.reverse(list) — reverses in-place Collections.shuffle(list) — random permutation Collections.rotate(list, distance) — rotates by distance positions Collections.swap(list, i, j) — swap two elements

CollectionsAlgorithms.java
import java.util.*;

public class CollectionsAlgorithms {
    public static void main(String[] args) {
        List<Integer> nums = new ArrayList<>(List.of(3, 1, 4, 1, 5, 9, 2, 6));

        // Sort + binary search
        Collections.sort(nums);
        System.out.println(nums); // [1, 1, 2, 3, 4, 5, 6, 9]
        int idx = Collections.binarySearch(nums, 5);
        System.out.println("Index of 5: " + idx); // 5

        // Reverse
        Collections.reverse(nums);
        System.out.println(nums); // [9, 6, 5, 4, 3, 2, 1, 1]

        // Shuffle (random order)
        Collections.shuffle(nums, new Random(42)); // seeded for reproducibility
        System.out.println(nums);

        // Rotate — moves last 'distance' elements to front
        List<String> letters = new ArrayList<>(List.of("a","b","c","d","e"));
        Collections.rotate(letters, 2);
        System.out.println(letters); // [d, e, a, b, c]

        // Swap
        Collections.swap(letters, 0, 4);
        System.out.println(letters); // [c, e, a, b, d]

        // Fill and nCopies
        Collections.fill(letters, "x");
        System.out.println(letters); // [x, x, x, x, x]

        List<String> copies = Collections.nCopies(4, "Java");
        System.out.println(copies); // [Java, Java, Java, Java]
    }
}

Frequency, Min/Max & Set Operations

Collections.frequency(col, obj) — count occurrences Collections.min/max(col) — natural order extreme; overload takes Comparator Collections.disjoint(c1, c2) — true if collections share no elements Collections.addAll(col, elements…) — varargs bulk add Collections.replaceAll (List method, not Collections) — replaceAll(UnaryOperator)

CollectionsStats.java
import java.util.*;

public class CollectionsStats {
    public static void main(String[] args) {
        List<String> words = List.of("apple","banana","apple","cherry","apple","banana");

        // Frequency
        System.out.println(Collections.frequency(words, "apple"));  // 3
        System.out.println(Collections.frequency(words, "grape"));  // 0

        // Min / Max
        System.out.println(Collections.min(words)); // apple (alphabetical)
        System.out.println(Collections.max(words)); // cherry

        // Min/Max with Comparator — longest word
        System.out.println(Collections.max(words, Comparator.comparingInt(String::length))); // banana/cherry

        // Disjoint — do the two collections share any element?
        List<Integer> a = List.of(1, 2, 3);
        List<Integer> b = List.of(4, 5, 6);
        List<Integer> c = List.of(3, 4, 5);
        System.out.println(Collections.disjoint(a, b)); // true
        System.out.println(Collections.disjoint(a, c)); // false

        // addAll — varargs bulk add to a mutable collection
        List<String> mutable = new ArrayList<>();
        Collections.addAll(mutable, "one", "two", "three");
        System.out.println(mutable); // [one, two, three]

        // replaceAll on list (List method, not Collections)
        mutable.replaceAll(String::toUpperCase);
        System.out.println(mutable); // [ONE, TWO, THREE]
    }
}

Unmodifiable & Synchronized Wrappers

Collections.unmodifiableXxx() wraps a mutable collection to throw UnsupportedOperationException on any mutating method. The underlying collection is still mutable — changes through the original reference are visible through the wrapper.

Collections.synchronizedXxx() wraps each method with synchronized. Still requires manual synchronisation when iterating (compound operations are not atomic).

Prefer List.of(), Set.of(), Map.of() (Java 9+) over unmodifiable wrappers for truly immutable collections.

WrapperCollections.java
import java.util.*;
import java.util.concurrent.*;

public class WrapperCollections {
    public static void main(String[] args) {
        List<String> mutable = new ArrayList<>(List.of("a", "b", "c"));
        List<String> readOnly = Collections.unmodifiableList(mutable);

        System.out.println(readOnly); // [a, b, c]

        try {
            readOnly.add("d"); // throws UnsupportedOperationException
        } catch (UnsupportedOperationException e) {
            System.out.println("Cannot modify unmodifiable list");
        }

        // Changes to original ARE visible through wrapper (it's a view)
        mutable.add("d");
        System.out.println(readOnly); // [a, b, c, d] — reflects change!

        // For truly immutable: use List.of() (Java 9+)
        List<String> immutable = List.of("x", "y", "z");
        // immutable.add("w"); // UnsupportedOperationException, and no backdoor

        // Synchronized wrapper — manual sync needed for iteration
        List<String> syncList = Collections.synchronizedList(new ArrayList<>(List.of("1","2","3")));
        synchronized (syncList) { // must manually lock for iteration
            for (String s : syncList) System.out.print(s + " ");
        }
        System.out.println();

        // Better for concurrent use: CopyOnWriteArrayList (read-heavy)
        List<String> cowList = new CopyOnWriteArrayList<>(List.of("a","b"));
        cowList.add("c");
        for (String s : cowList) System.out.print(s + " "); // no CME
    }
}

Key Points to Remember

  • Collections.sort requires Comparable elements or a Comparator; uses stable TimSort
  • Collections.binarySearch requires a pre-sorted list — undefined behaviour on unsorted lists
  • Collections.unmodifiableList is a view — the underlying list can still be mutated through its original reference
  • List.of() / Set.of() / Map.of() (Java 9+) create truly immutable collections with no backdoor
  • Collections.synchronizedList requires manual lock on the collection during iteration
  • Collections.disjoint is an efficient O(n) check for shared elements between two collections

Practice Collections Utility Methods in the Playground

Run and modify code directly in your browser - no setup needed.

Interview Questions

Sign in to ask Aria
1

What is the difference between Collections.sort() and List.sort()?

EasyTCS
2

What is the difference between Collections.unmodifiableList and List.of()?

MediumAmazon
3

Why do you need to synchronize manually when iterating a synchronizedList?

MediumGoogle
4

What does Collections.rotate() do?

EasyOracle
5

What does Collections.disjoint() return?

EasyMicrosoft

Ask Aria about Collections Utility Methods

Your personal AI tutor — ask anything about this concept