Java
Sorting
Programming
Java Collections
Multi-field Sorting

How to sort by two fields in Java?

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Sorting collections of objects by multiple fields is a common necessity in Java programming, especially when dealing with complex data models. Here's a detailed guide on how to sort by two fields in Java.

Introduction

When working with lists of objects, it's often necessary to impose an order. For instance, consider a list of Person objects, where you want to sort first by the last name and then by the first name. Java provides several ways to achieve this, which we will explore in this article using the Comparator interface and Java 8+ features like lambda expressions and method references.

Comparator in Java

The Comparator interface in Java is a powerful feature that allows objects to be ordered by defining custom sorting logic.

Using Comparator Prior to Java 8

Before Java 8, sorting a list by multiple fields involved implementing a Comparator class or using anonymous classes. Here’s how you can do it:

  1. Define a class implementing Comparator:
java
1import java.util.*;
2
3class Person {
4    String firstName;
5    String lastName;
6    
7    Person(String firstName, String lastName) {
8        this.firstName = firstName;
9        this.lastName = lastName;
10    }
11    
12    // Getters omitted for brevity
13}
14    
15class PersonComparator implements Comparator<Person> {
16    @Override
17    public int compare(Person p1, Person p2) {
18        // First sort by last name
19        int nameCompare = p1.lastName.compareTo(p2.lastName);
20        if (nameCompare == 0) {
21            // Then sort by first name
22            return p1.firstName.compareTo(p2.firstName);
23        }
24        return nameCompare;
25    }
26}
27
28public class Main {
29    public static void main(String[] args) {
30        List<Person> people = Arrays.asList(
31            new Person("Alice", "Zephyr"),
32            new Person("Alice", "Young"),
33            new Person("Charlie", "Young"),
34            new Person("Bob", "Amos")
35        );
36
37        Collections.sort(people, new PersonComparator());
38
39        people.forEach(p -> System.out.println(p.lastName + ", " + p.firstName));
40    }
41}

Using Comparator in Java 8 and Later

Java 8 introduced lambda expressions and the Comparator interface’s static and default methods, which made sorting more concise and readable.

  1. Using Lambda Expressions:
java
1import java.util.*;
2
3public class LambdaSortExample {
4    public static void main(String[] args) {
5        List<Person> people = Arrays.asList(
6            new Person("Alice", "Zephyr"),
7            new Person("Alice", "Young"),
8            new Person("Charlie", "Young"),
9            new Person("Bob", "Amos")
10        );
11
12        people.sort(Comparator.comparing(Person::getLastName)
13                              .thenComparing(Person::getFirstName));
14
15        people.forEach(p -> System.out.println(p.lastName + ", " + p.firstName));
16    }
17}
  1. Using Method References:

Java 8 also supports method references, which can make your code cleaner:

java
people.sort(Comparator.comparing(Person::getLastName)
                      .thenComparing(Comparator.comparing(Person::getFirstName)));

Details on Comparator Methods

  • Comparator.comparing(): This method generates a Comparator for a specific field using a key extractor function.
  • thenComparing(): Allows additional specifications for the Comparator, enabling multi-level sorting.

Performance Considerations

Sorting algorithms in Java utilize mergesort or timsort (a derivative of mergesort). Both are stable and run in O(n log n) time complexity. Using multi-level sorting doesn’t change this complexity since each additional level of sorting is linear O(n) relative to the already sorted structure.

Summary Table

FeatureDescription
Comparator.comparing()Generates a Comparator for a specific field.
thenComparing()Chaining method for multi-level sorting.
Lambda ExpressionsProvides in-line, anonymous implementation of Comparator.
Method ReferencesCleaner syntax for referencing methods directly.
Time ComplexityO(n log n) due to timsort/mergesort.
StabilityPreserves order of equal elements across different fields.

Conclusion

Sorting by multiple fields in Java is a straightforward task, especially with the enhancements provided in Java 8 and beyond. The use of Comparator, lambda expressions, and method references offers flexibility and cleaner code. Whether dealing with existing collections or custom objects, Java provides robust mechanisms to implement complex sorting.


Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.