Fundamentals 31 min read

Master Java’s Comparator: Sorting Collections, Streams, and Sets Made Easy

This article explains Java's Comparator interface, its compare method, lambda definitions, and how to use it with Collections.sort, List.sort, Arrays.sort, Stream.sorted, as well as with SortedSet and SortedMap structures, covering static and default methods like reversed, nullsFirst, thenComparing, and more.

Programmer DD
Programmer DD
Programmer DD
Master Java’s Comparator: Sorting Collections, Streams, and Sets Made Easy

Java's java.util.Comparator functional interface imposes a total ordering on object collections.

Comparator Functional Method

The core method is int compare(T o1, T o2), which returns a negative integer, zero, or a positive integer when the first argument is less than, equal to, or greater than the second argument. The ordering must be consistent with equals —i.e., c.compare(e1, e2) == 0 should have the same boolean result as e1.equals(e2).

Comparator Method Signature

int compare(T o1, T o2)

Defining Comparators with Lambda Expressions

Lambda expressions can be used to create comparator instances concisely:

Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
Comparator<Student> nameComp = (s1, s2) -> s1.getName().compareTo(s2.getName());

Using Comparator with Sorting APIs

The comparator can be passed to various sorting methods:

Stream.sorted(comparator)
Collections.sort(list, comparator)
List.sort(comparator)
Arrays.sort(array, comparator)

Example with List.sort:

List<Student> list = Student.getStudentList();
Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
list.sort(ageComp);
list.forEach(System.out::println);

Comparator with Stream.sorted

list.stream()
    .sorted(ageComp)
    .forEach(System.out::println);

Comparator with Collections.sort

Collections.sort(list, ageComp);
list.forEach(System.out::println);

Comparator with Arrays.sort

Student[] array = {s1, s2, s3};
Arrays.sort(array, ageComp);
for (Student s : array) {
    System.out.println(s);
}

Static and Default Methods (Java 8+)

Comparator provides several useful static and default methods: default Comparator<T> reversed() – returns a comparator that imposes the reverse ordering. static <T> Comparator<T> reverseOrder() – returns a comparator that imposes the reverse of the natural order. static <T> Comparator<T> naturalOrder() – returns a comparator that imposes the natural order.

static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator)

– treats null as less than non‑null.

static <T> Comparator<T> nullsLast(Comparator<? super T> comparator)

– treats null as greater than non‑null.

static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)

– creates a comparator based on a key extractor.

static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor)
static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor)
static <T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor)
default Comparator<T> thenComparing(Comparator<? super T> other)
default <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T,? extends U> keyExtractor)
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor)
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor)
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor)

Examples of Static Methods

reversed :

Comparator<Student> nameComparator = (s1, s2) -> s1.getName().compareTo(s2.getName());
Collections.sort(list, nameComparator.reversed());

nullsFirst :

List<Student> list = Arrays.asList(s1, s2, null, s3);
Collections.sort(list, Comparator.nullsFirst(Comparator.comparing(Student::getName)));

comparingInt (sorting by age):

Collections.sort(list, Comparator.comparingInt(Student::getAge));

comparingLong (sorting by home distance):

Collections.sort(list, Comparator.comparingLong(Student::getHomeDistance));

comparingDouble (sorting by weight):

Collections.sort(list, Comparator.comparingDouble(Student::getWeight));

Chaining Comparators with thenComparing

Example: first sort by age, then by name:

Comparator<Student> comp = Comparator.comparing(Student::getAge)
    .thenComparing(Student::getName);
Collections.sort(list, comp);

More complex chaining can involve multiple keys and custom comparators.

Comparator with SortedSet

TreeSet and ConcurrentSkipListSet can be constructed with a comparator to control element order:

Comparator<Student> ageComparator = Comparator.comparing(Student::getAge);
TreeSet<Student> treeSet = new TreeSet<>(ageComparator);
treeSet.addAll(Arrays.asList(s1, s2, s3));

When no comparator is supplied, the set relies on the elements' natural ordering (i.e., they must implement Comparable).

Comparator with SortedMap

TreeMap and ConcurrentSkipListMap accept a comparator to order their keys:

Comparator<Student> ageComparator = Comparator.comparing(Student::getAge);
TreeMap<Student, String> treeMap = new TreeMap<>(ageComparator);
treeMap.put(s1, "Varanasi");

Without a comparator, the map orders keys according to their natural order.

Conclusion

The Comparator interface is a versatile tool for defining custom ordering in Java. By leveraging lambda expressions, static factory methods, and default chaining methods, developers can sort collections, streams, sets, and maps in a concise and expressive manner.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaLambdaStreamsSortingComparatorTreeSetTreeMap
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.