How is Comparator an example of the Strategy pattern in the JDK, and how do you use it to vary sort order at runtime?
answer
- Comparator = swappable ordering rule = Strategy
- compare(a,b) → negative / zero / positive
- Sort engine fixed (TimSort), rule passed in
- Collections.sort(list, comparator) / list.sort(comparator)
- Comparator (external) vs Comparable (natural, built-in)
basics
~20 sA Comparator is a small object that says how to order two items. You pass different Comparators to Collections.sort or List.sort to get different orderings without changing the sort code. That swappable rule is the Strategy pattern.
solid answer
~40 sThe Strategy pattern lets you pick an algorithm at runtime by passing it in as an object. In the JDK, Comparator is the textbook example: sort methods like Collections.sort(list, comparator) and List.sort(comparator) take a Comparator that defines the ordering rule, while the sort algorithm itself stays fixed. To order people by name you pass one Comparator; to order by age you pass another; the calling code chooses which 'strategy' at runtime. Comparator.compare(a, b) returns negative, zero, or positive, which the sort uses to arrange elements. Since Comparator is a functional interface (one abstract method), you can supply the strategy as a lambda — Comparator.comparing(Person::getAge) — keeping it lightweight. This is why you can sort the same list many different ways without touching the elements or the sort engine.
code
java · 10 linesrecord Person(String name, int age) {}
List<Person> people = new ArrayList<>(List.of(
new Person("Ada", 36), new Person("Bob", 28)));
Comparator<Person> byName = Comparator.comparing(Person::name);
Comparator<Person> byAge = Comparator.comparingInt(Person::age);
people.sort(byName); // choose ordering strategy at runtime
people.sort(byAge); // same list, different strategy, same sort enginego deeper
Can state that a Comparator is a rule for ordering two items and that passing different Comparators to sort produces different orderings.
Explains the compare contract (sign of the int), distinguishes Comparator from Comparable, and connects 'pass the rule in' to the Strategy pattern.
Frames Comparator as Strategy precisely — fixed context (sort engine) vs interchangeable algorithm (ordering) chosen at runtime — and lists the JDK touchpoints (sort, TreeMap/Set, Stream.sorted, PriorityQueue).
Discusses why externalizing ordering as a strategy is the right design (open/closed, no element-class edits), the functional-interface synergy enabling lightweight strategies, and trade-offs vs natural ordering and stability guarantees.
## What the Strategy pattern is The **Strategy pattern** is a design pattern where you define a family of interchangeable algorithms, put each one behind a common interface, and let the caller choose which one to use **at runtime**. The code that *uses* the algorithm (the 'context') doesn't hard-code one behavior — it holds a reference to the strategy interface and delegates to whatever concrete strategy was handed to it. Analogy: a navigation app has one 'find a route' button (the context) but several routing strategies — fastest, shortest, avoid tolls. You pick a strategy; the button's code never changes. ## Why sorting needs this Sorting has two separable concerns: 1. **The sort algorithm** — how elements get rearranged (the JDK uses a stable, optimized merge/insertion sort called TimSort). This is fixed and you rarely care about it. 2. **The ordering rule** — given two elements, which comes first? This varies constantly: by name, by age, descending, by last name then first name. If ordering were baked into the sort, you'd need a different sort method per ordering. Instead the JDK factors the ordering rule out into a **strategy object** you pass in. ## Comparator: the strategy interface `java.util.Comparator<T>` is that strategy interface. Its single core method is: ```java int compare(T a, T b); ``` The contract: return a **negative** number if `a` should come before `b`, **zero** if they're equal in ordering, **positive** if `a` should come after `b`. The sort engine calls `compare` repeatedly and uses the sign to arrange elements. The JDK sort entry points accept this strategy: - `Collections.sort(List<T> list, Comparator<? super T> c)` - `list.sort(Comparator<? super T> c)` (on `List`) - `Arrays.sort(T[] a, Comparator<? super T> c)` - It also flows through `TreeMap`, `TreeSet`, `Stream.sorted(comparator)`, `PriorityQueue`, etc. ## Varying order at runtime Because the rule is a parameter, the *same* list can be sorted many ways by passing a different `Comparator`: ```java List<Person> people = ...; people.sort(byName); // one strategy people.sort(byAge); // a different strategy, same sort engine ``` The choice can be made dynamically — e.g. from a user clicking a column header — so it is genuinely a *runtime* selection, the defining trait of Strategy. ## Comparator vs Comparable There are two related JDK pieces: - **`Comparable<T>`** (method `compareTo`) defines an element's **one natural ordering**, built into the class itself (e.g. `String` is alphabetical, `Integer` is numeric). This is more like a fixed default. - **`Comparator<T>`** is an **external, swappable** ordering — the Strategy. You provide as many as you like, none of which require modifying the element class. Sorting without a comparator (`Collections.sort(list)`) uses the elements' natural `Comparable` ordering; sorting *with* a comparator overrides it with your strategy. ## Why it's lightweight in modern Java `Comparator` has exactly one abstract method, so it is a **functional interface** — you can write the strategy as a **lambda** or method reference instead of a whole class: ```java people.sort((a, b) -> a.getName().compareTo(b.getName())); people.sort(Comparator.comparing(Person::getName)); ``` This makes passing a strategy almost free, which is why Strategy-via-Comparator is so pervasive in idiomatic Java.
- What's the difference between Comparable and Comparator?Comparable (compareTo) is the element's single natural ordering, baked into the class. Comparator (compare) is an external, swappable ordering you pass to sort — multiple strategies, no change to the element class.
- What must compare(a, b) return?An int: negative if a comes before b, zero if equal in ordering, positive if a comes after b. Only the sign matters, not the magnitude.
A sort method is like a single 'sort' button on a spreadsheet; the Comparator is the column you tell it to sort by. Same button, different rule each time.
saying these in an interview costs you the question
- Thinking compare returns a boolean — it returns an int whose sign matters
- Confusing Comparator (external, many) with Comparable (one natural ordering)
- Claiming you must modify the element class to change sort order
- Saying Strategy changes the sort algorithm — it changes the ordering rule, not the engine