Skip to content
intermediate Phase 5 · Java Collections

Collections Utility Class

Use Collections.sort(), reverse(), shuffle(), and other utility methods.

30m
2 problems
Topic Progress 0%

Sorting

Sorting with Collections

The Collections class provides static methods for sorting, reversing, and shuffling lists.

import java.util.*;

public class SortingDemo {
    public static void main(String[] args) {
        // Sort - natural ordering
        List<Integer> numbers = new ArrayList<>(Arrays.asList(5, 2, 8, 1, 9, 3));
        Collections.sort(numbers);
        System.out.println("Sorted: " + numbers); // [1, 2, 3, 5, 8, 9]

        // Sort - custom comparator
        List<String> names = new ArrayList<>(Arrays.asList("Charlie", "Alice", "Bob"));
        Collections.sort(names); // natural alphabetical
        System.out.println("Alphabetical: " + names); // [Alice, Bob, Charlie]

        Collections.sort(names, Comparator.reverseOrder());
        System.out.println("Reverse alpha: " + names); // [Charlie, Bob, Alice]

        // Sort by string length
        Collections.sort(names, Comparator.comparingInt(String::length));
        System.out.println("By length: " + names); // [Bob, Alice, Charlie]

        // Reverse
        List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
        Collections.reverse(list);
        System.out.println("Reversed: " + list); // [5, 4, 3, 2, 1]

        // Shuffle
        List<Integer> shuffled = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
        Collections.shuffle(shuffled);
        System.out.println("Shuffled: " + shuffled); // random order

        // Rotate
        List<Integer> rotated = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
        Collections.rotate(rotated, 2); // rotate right by 2
        System.out.println("Rotated: " + rotated); // [4, 5, 1, 2, 3]

        // Fill - replace all elements
        List<String> filled = new ArrayList<>(Arrays.asList("a", "b", "c"));
        Collections.fill(filled, "x");
        System.out.println("Filled: " + filled); // [x, x, x]

        // Swap
        List<Integer> swapped = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
        Collections.swap(swapped, 0, 4); // swap indices 0 and 4
        System.out.println("Swapped: " + swapped); // [5, 2, 3, 4, 1]

        // Min and Max
        System.out.println("Min: " + Collections.min(numbers));
        System.out.println("Max: " + Collections.max(numbers));

        // Sort with nulls last
        List<String> withNulls = new ArrayList<>(Arrays.asList("b", null, "a", null, "c"));
        withNulls.sort(Comparator.nullsLast(Comparator.naturalOrder()));
        System.out.println("Nulls last: " + withNulls); // [a, b, c, null, null]
    }
}

Note: Collections.sort() modifies the list in place. For a new sorted list without modifying the original, use list.stream().sorted().collect(Collectors.toList()) or create a copy first.

Unmodifiable

Unmodifiable Collections

The Collections class provides wrappers that make collections immutable. Any attempt to modify throws UnsupportedOperationException.

import java.util.*;

public class UnmodifiableDemo {
    public static void main(String[] args) {
        // Unmodifiable List
        List<String> mutable = new ArrayList<>(Arrays.asList("a", "b", "c"));
        List<String> unmodifiable = Collections.unmodifiableList(mutable);
        System.out.println("Unmodifiable: " + unmodifiable); // [a, b, c]

        // Cannot modify
        try {
            unmodifiable.add("d");
        } catch (UnsupportedOperationException e) {
            System.out.println("Cannot modify: " + e.getMessage());
        }

        // BUT: modifying the original list affects the view!
        mutable.add("d");
        System.out.println("Original: " + mutable); // [a, b, c, d]
        System.out.println("View: " + unmodifiable); // [a, b, c, d]

        // Truly immutable - copy the list
        List<String> immutable = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("x", "y", "z")));
        mutable.add("e"); // doesn't affect immutable
        System.out.println("Immutable: " + immutable); // [x, y, z]

        // Unmodifiable Map
        Map<String, Integer> map = new HashMap<>();
        map.put("a", 1);
        map.put("b", 2);
        Map<String, Integer> unmodMap = Collections.unmodifiableMap(map);
        System.out.println("Unmodifiable map: " + unmodMap);

        // Unmodifiable Set
        Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3));
        Set<Integer> unmodSet = Collections.unmodifiableSet(set);
        System.out.println("Unmodifiable set: " + unmodSet);

        // Java 9+ shortcut
        List<String> ofList = List.of("a", "b", "c"); // truly immutable
        Map<String, Integer> ofMap = Map.of("a", 1, "b", 2); // truly immutable
        System.out.println("List.of: " + ofList);
        System.out.println("Map.of: " + ofMap);
    }
}

Key distinction:

  • Collections.unmodifiableList(list) — wrapper that delegates to the original list. Changes to the original are visible through the wrapper.
  • List.of(...) (Java 9+) — truly immutable copy. No connection to any other list.

Singleton

Collections.singleton()

The singleton methods return immutable sets containing exactly one element. They are more memory-efficient than creating a full HashSet for a single element.

import java.util.*;

public class SingletonDemo {
    public static void main(String[] args) {
        // Singleton Set
        Set<String> single = Collections.singleton("Hello");
        System.out.println("Singleton set: " + single); // [Hello]
        System.out.println("Size: " + single.size()); // 1
        System.out.println("Contains: " + single.contains("Hello")); // true

        // Cannot modify
        try {
            single.add("World");
        } catch (UnsupportedOperationException e) {
            System.out.println("Cannot add: immutable");
        }

        // Singleton List
        List<Integer> singleList = Collections.singletonList(42);
        System.out.println("Singleton list: " + singleList); // [42]

        // Singleton Map
        Map<String, Integer> singleMap = Collections.singletonMap("key", 100);
        System.out.println("Singleton map: " + singleMap); // {key=100}

        // Use cases
        System.out.println("\n--- Use Cases ---");

        // 1. Method returning immutable single-element collection
        Set<String> getPermissions() {
            return Collections.singleton("READ");
        }

        // 2. As argument to methods expecting Collection
        List<String> list = new ArrayList<>(Collections.singleton("default"));
        System.out.println("From singleton: " + list); // [default]

        // 3. Default value pattern
        String input = null;
        Set<String> values = input != null ?
            Set.of(input) : Collections.singleton("default");
        System.out.println("Default: " + values); // [default]

        // Java 9+ alternative
        Set<String> java9 = Set.of("Hello"); // also immutable, one element
        System.out.println("Java 9 Set.of: " + java9);
    }

    // Method returning singleton set
    static Set<String> getPermissions() {
        return Collections.singleton("READ");
    }
}

When to use singleton:

  • Returning a single-element immutable collection from a method
  • As a default value when no data is available
  • When you need a Collection type but only have one element
  • Memory-efficient alternative to new HashSet<>(Arrays.asList(e))

Utility Methods

Other Utility Methods

The Collections class provides many other useful utility methods.

import java.util.*;

public class UtilityMethodsDemo {
    public static void main(String[] args) {
        // Frequency - count occurrences
        List<String> list = Arrays.asList("a", "b", "a", "c", "a", "b");
        System.out.println("Frequency of a: " + Collections.frequency(list, "a")); // 3
        System.out.println("Frequency of b: " + Collections.frequency(list, "b")); // 2
        System.out.println("Frequency of d: " + Collections.frequency(list, "d")); // 0

        // Disjoint - check if two collections have no common elements
        Set<Integer> setA = new HashSet<>(Arrays.asList(1, 2, 3));
        Set<Integer> setB = new HashSet<>(Arrays.asList(4, 5, 6));
        System.out.println("Disjoint: " + Collections.disjoint(setA, setB)); // true

        setB.add(3);
        System.out.println("Disjoint: " + Collections.disjoint(setA, setB)); // false

        // indexOfSubList - find sublist position
        List<Integer> main = Arrays.asList(1, 2, 3, 4, 5, 6);
        List<Integer> sub = Arrays.asList(3, 4);
        System.out.println("indexOfSubList: " + Collections.indexOfSubList(main, sub)); // 2

        // lastIndexOfSubList
        System.out.println("lastIndexOfSubList: " + Collections.lastIndexOfSubList(main, sub)); // 2

        // List.nCopies - create list with n copies of same element
        List<String> copies = Collections.nCopies(5, "hello");
        System.out.println("nCopies: " + copies); // [hello, hello, hello, hello, hello]

        // Enumeration (legacy - for backward compatibility)
        List<String> legacy = Arrays.asList("a", "b", "c");
        Enumeration<String> enumList = Collections.enumeration(legacy);
        while (enumList.hasMoreElements()) {
            System.out.print(enumList.nextElement() + " ");
        }
        System.out.println();

        // List from Enumeration
        List<String> fromEnum = Collections.list(Collections.enumeration(legacy));
        System.out.println("From enumeration: " + fromEnum);

        // synchronized wrappers
        List<String> syncList = Collections.synchronizedList(new ArrayList<>());
        Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());
        Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());
        System.out.println("Created synchronized collections");
    }
}

Summary of key methods:

  • frequency(collection, obj) — count occurrences
  • disjoint(col1, col2) — check if no common elements
  • nCopies(n, obj) — create list with n copies
  • indexOfSubList(list, sub) — find sublist position
  • synchronizedList/Map/Set — thread-safe wrappers

Practice Problems

0 / 2 solved
Sort an Array
Sorting

Given an array of integers nums, sort the array in ascending order.

Example:

Input: nums = [5, 2, 3, 1]

Output: [1, 2, 3, 5]

Sort in ascending order

Kth Largest Element
Sorting

Find the kth largest element in an unsorted array.

Example:

Input: nums = [3, 2, 1, 5, 6, 4], k = 2

Output: 5

The 2nd largest element is 5

Quiz

1. What does Collections.unmodifiableList() return?

Question 1 options

2. What is the purpose of Collections.singleton()?

Question 2 options

3. How do you count occurrences of an element in a list?

Question 3 options

Flashcards

Question

What does Collections.sort() do?

Answer

Sorts the list in-place according to natural ordering or a custom Comparator. Time complexity is O(n log n). Modifies the original list.

Question

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

Answer

unmodifiableList() is a wrapper that delegates to the original list. List.of() creates a truly immutable copy. Changes to the original are visible through unmodifiableList but not List.of.

Question

How do you create a thread-safe collection using Collections utility?

Answer

Use Collections.synchronizedList(), synchronizedMap(), or synchronizedSet(). These wrap the collection with synchronized access. For concurrent access, consider java.util.concurrent classes instead.

Revision Notes

Key Takeaways

  • 1. Collections.sort() modifies the list in-place
  • 2. unmodifiableList() is a wrapper — changes to original are visible
  • 3. singleton() is memory-efficient for single-element immutable collections
  • 4. frequency() counts occurrences of an element in a collection

Interview Tips

  • Know that unmodifiableList is a wrapper, not a copy
  • Understand when to use List.of() vs Collections.unmodifiableList()
  • Be aware of Collections.sort() modifying the original list
  • Know the utility methods: frequency, disjoint, nCopies

Cheat Sheet

Collections Utility Cheat Sheet

Sorting & Ordering

  • sort(list) → O(n log n), in-place
  • reverse(list) → reverse in-place
  • shuffle(list) → random order
  • rotate(list, dist) → rotate elements
  • swap(list, i, j) → swap two elements

Unmodifiable

  • unmodifiableList/Map/Set → wrapper view
  • Changes to original visible through wrapper!
  • For true immutability: new ArrayList<>(list)

Singleton

  • singleton(e) → immutable set with one element
  • singletonList(e) → immutable list with one element
  • singletonMap(k, v) → immutable map with one entry

Utility

  • frequency(collection, obj) → count occurrences
  • disjoint(col1, col2) → no common elements
  • nCopies(n, obj) → list with n copies