A custom comparator is applied in a stream pipeline by passing a Comparator implementation, often built with Comparator.comparing(), to the sorted() intermediate operation, letting you control ordering by any field or combination of fields.
Key Points: • Comparator.comparing(keyExtractor) builds a comparator from a method reference or lambda that extracts the field to sort by. • thenComparing() chains a secondary comparator for tie-breaking when the primary field is equal. • reversed() flips a comparator to descending order without writing separate compare logic. • Comparator.comparing() has overloads accepting a second key-comparator argument for non-Comparable fields or custom ordering. • The resulting Comparator is passed directly into sorted(comparator) within the stream pipeline.
Example: employees.stream().sorted(Comparator.comparing(Employee::getDepartment).thenComparing(Employee::getName)) sorts employees first by department, then alphabetically by name within each department.
Code Example:
List<Employee> employees = getEmployees();
List<Employee> sorted = employees.stream()
.sorted(Comparator.comparing(Employee::getSalary).reversed())
.collect(Collectors.toList());Interview Tip: A concise interview answer is:
"I build a Comparator with Comparator.comparing() and a key extractor, optionally chaining thenComparing() for tie-breaks or reversed() for descending order, then pass it straight into sorted() in the pipeline. It keeps sorting logic declarative and lets me sort by fields that aren't naturally Comparable."