Collections Utility & Comparators
Collections Utility & Comparators
The java.util.Collections class is a toolkit of static helper methods that operate on List, Set, and Map instances. It handles sorting, searching, shuffling, frequency counting, and wrapping collections in read-only or thread-safe views — all without you writing the algorithm yourself. In this lesson you will also learn how to build expressive, chainable Comparator objects so you can sort on any criteria you need.
Sorting with Collections.sort
The simplest use of the utility class is sorting a List whose elements implement Comparable. Strings and numbers already implement it, so sorting them takes one line:
Under the hood, Collections.sort delegates to List.sort, which uses a stable merge sort (TimSort). Stable means equal elements keep their original relative order — important when you sort by one field and previously sorted by another.
list.sort(comparator) is the idiomatic choice — it is equally efficient and reads more naturally. Collections.sort is older but still widely seen in code you will maintain.
Reversing and Shuffling
Collections.reverse reverses the order of a list in place. Collections.shuffle randomises it, optionally with a seeded Random for reproducibility:
Unmodifiable and Synchronized Views
Sometimes you want to share a collection with other code but prevent that code from changing it. Collections.unmodifiableList (and the equivalent for Set and Map) wraps the original collection in a view that throws UnsupportedOperationException on any write:
mutable above, readOnly will reflect the change. For a truly immutable snapshot, use List.copyOf(mutable) (Java 10+).
Collections.synchronizedList wraps a list so each individual method call is thread-safe. For more demanding concurrency use CopyOnWriteArrayList or ConcurrentHashMap instead — but the synchronized wrappers are a quick option when you just need basic safety.
Other Handy Utility Methods
Collections.min(coll)/Collections.max(coll)— find the smallest or largest element.Collections.frequency(coll, obj)— count how many timesobjappears.Collections.nCopies(n, obj)— create an immutable list ofncopies ofobj(useful for padding or default values).Collections.disjoint(c1, c2)— returnstrueif the two collections share no elements.Collections.swap(list, i, j)— swap elements at two positions.
Building Comparators
When elements do not implement Comparable, or you want a different sort order, you pass a Comparator. The factory method Comparator.comparing creates one from a key-extractor function:
Chaining Comparators
Real sorting often requires a primary key, then a tiebreaker. Comparator provides thenComparing for exactly this:
Reversing and Null-Safe Comparators
Call .reversed() on any comparator to flip its order without rewriting the key extractor:
If a key can be null, wrap the comparator with Comparator.nullsFirst or Comparator.nullsLast:
Comparator into a static final constant. This makes tests straightforward and avoids subtle bugs from accidentally building the comparator differently each time.
Putting It Together
Here is a realistic example combining the utility class and a chained comparator:
Summary
The Collections utility class gives you production-quality algorithms (sort, reverse, shuffle, min/max, frequency, unmodifiable/synchronized views) in a single import. The Comparator API lets you express any sort criterion with readable, composable code — chaining thenComparing, reversed, and null-safe wrappers instead of writing nested if blocks. Together they complete the Collections Framework toolbox you have built across this tutorial.