Your Comparator would look like this:

public class GraduationCeremonyComparator implements Comparator<GraduationCeremony> {
    public int compare(GraduationCeremony o1, GraduationCeremony o2) {
        int value1 = o1.campus.compareTo(o2.campus);
        if (value1 == 0) {
            int value2 = o1.faculty.compareTo(o2.faculty);
            if (value2 == 0) {
                return o1.building.compareTo(o2.building);
            } else {
                return value2;
            }
        }
        return value1;
    }
}

Basically it continues comparing each successive attribute of your class whenever the compared attributes so far are equal (== 0).

Answer from Daniel DiPaolo on Stack Overflow
Top answer
1 of 6
76

Your Comparator would look like this:

public class GraduationCeremonyComparator implements Comparator<GraduationCeremony> {
    public int compare(GraduationCeremony o1, GraduationCeremony o2) {
        int value1 = o1.campus.compareTo(o2.campus);
        if (value1 == 0) {
            int value2 = o1.faculty.compareTo(o2.faculty);
            if (value2 == 0) {
                return o1.building.compareTo(o2.building);
            } else {
                return value2;
            }
        }
        return value1;
    }
}

Basically it continues comparing each successive attribute of your class whenever the compared attributes so far are equal (== 0).

2 of 6
43

Yes, you absolutely can do this. For example:

public class PersonComparator implements Comparator<Person>
{
    public int compare(Person p1, Person p2)
    {
        // Assume no nulls, and simple ordinal comparisons

        // First by campus - stop if this gives a result.
        int campusResult = p1.getCampus().compareTo(p2.getCampus());
        if (campusResult != 0)
        {
            return campusResult;
        }

        // Next by faculty
        int facultyResult = p1.getFaculty().compareTo(p2.getFaculty());
        if (facultyResult != 0)
        {
            return facultyResult;
        }

        // Finally by building
        return p1.getBuilding().compareTo(p2.getBuilding());
    }
}

Basically you're saying, "If I can tell which one comes first just by looking at the campus (before they come from different campuses, and the campus is the most important field) then I'll just return that result. Otherwise, I'll continue on to compare faculties. Again, stop if that's enough to tell them apart. Otherwise, (if the campus and faculty are the same for both people) just use the result of comparing them by building."

๐ŸŒ
Baeldung
baeldung.com โ€บ home โ€บ java โ€บ java collections โ€บ sort collection of objects by multiple fields in java
Sort Collection of Objects by Multiple Fields in Java | Baeldung
January 8, 2024 - Weโ€™ll be comparing Person objects first based on name and then on age throughout our examples: public class Person { @Nonnull private String name; private int age; // constructor // getters and setters } Here, weโ€™ve added a @Nonnull annotation to keep the examples simple. But in production code, we may need to handle the comparison of nullable fields. Java provides the Comparator interface for comparing two objects of the same type.
๐ŸŒ
Benchresources
benchresources.net โ€บ home โ€บ java โ€บ java 8 โ€“ sorting list of objects on multiple fields
Java 8 - Sorting list of objects on multiple fields - BenchResources.Net
October 18, 2022 - In this approach, we are going to pass 3 Comparators to sorted() method using thenComparing() method one-by-one using Method Reference ยท package net.bench.resources.stream.sorting.multiple.fields; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; public class CustomerSortingUsingJava8Comparing { // customer list private static List<Customer> getUnSortedCustomers() { return Arrays.asList( new Customer("Shalini", "Chennai", 60), new Customer("Sneha", "Pune", 73), new Customer("Simran", "Bangalore", 37), new Customer("Trisha", "Hyder
๐ŸŒ
BezKoder
bezkoder.com โ€บ home โ€บ java โ€“ sort arraylist of objects
Java - Sort ArrayList of Objects - BezKoder
December 27, 2019 - You will know how to: sort ArrayList of Objects by one field or multiple fields use custom Comparator to sort ArrayList of Objects implement Comparable interface to sort ArrayList of Objects conveniently Java ArrayList [โ€ฆ]
๐ŸŒ
Java67
java67.com โ€บ 2017 โ€บ 07 โ€บ how-to-sort-arraylist-of-objects-using.html
How to Sort ArrayList of Objects by Fields in Java? Custom + Reversed Order Sorting Comparator Example | Java67
In order to sort an ArrayList of custom or user-defined objects, you need two things, first a class to provide ordering and a method to provide sorting. If you know about ordering and sorting in Java then you know that the Comparable and Comparator ...
Top answer
1 of 15
190

(originally from Ways to sort lists of objects in Java based on multiple fields)

Original working code in this gist

Using Java 8 lambda's (added April 10, 2019)

Java 8 solves this nicely by lambda's (though Guava and Apache Commons might still offer more flexibility):

Collections.sort(reportList, Comparator.comparing(Report::getReportKey)
            .thenComparing(Report::getStudentNumber)
            .thenComparing(Report::getSchool));

Thanks to @gaoagong's answer below.

Note that one advantage here is that the getters are evaluated lazily (eg. getSchool() is only evaluated if relevant).

Messy and convoluted: Sorting by hand

Collections.sort(pizzas, new Comparator<Pizza>() {  
    @Override  
    public int compare(Pizza p1, Pizza p2) {  
        int sizeCmp = p1.size.compareTo(p2.size);  
        if (sizeCmp != 0) {  
            return sizeCmp;  
        }  
        int nrOfToppingsCmp = p1.nrOfToppings.compareTo(p2.nrOfToppings);  
        if (nrOfToppingsCmp != 0) {  
            return nrOfToppingsCmp;  
        }  
        return p1.name.compareTo(p2.name);  
    }  
});  

This requires a lot of typing, maintenance and is error prone. The only advantage is that getters are only invoked when relevant.

The reflective way: Sorting with BeanComparator

ComparatorChain chain = new ComparatorChain(Arrays.asList(
   new BeanComparator("size"), 
   new BeanComparator("nrOfToppings"), 
   new BeanComparator("name")));

Collections.sort(pizzas, chain);  

Obviously this is more concise, but even more error prone as you lose your direct reference to the fields by using Strings instead (no typesafety, auto-refactorings). Now if a field is renamed, the compiler wonโ€™t even report a problem. Moreover, because this solution uses reflection, the sorting is much slower.

Getting there: Sorting with Google Guavaโ€™s ComparisonChain

Collections.sort(pizzas, new Comparator<Pizza>() {  
    @Override  
    public int compare(Pizza p1, Pizza p2) {  
        return ComparisonChain.start().compare(p1.size, p2.size).compare(p1.nrOfToppings, p2.nrOfToppings).compare(p1.name, p2.name).result();  
        // or in case the fields can be null:  
        /* 
        return ComparisonChain.start() 
           .compare(p1.size, p2.size, Ordering.natural().nullsLast()) 
           .compare(p1.nrOfToppings, p2.nrOfToppings, Ordering.natural().nullsLast()) 
           .compare(p1.name, p2.name, Ordering.natural().nullsLast()) 
           .result(); 
        */  
    }  
});  

This is much better, but requires some boiler plate code for the most common use case: null-values should be valued less by default. For null-fields, you have to provide an extra directive to Guava what to do in that case. This is a flexible mechanism if you want to do something specific, but often you want the default case (ie. 1, a, b, z, null).

And as noted in the comments below, these getters are all evaluated immediately for each comparison.

Sorting with Apache Commons CompareToBuilder

Collections.sort(pizzas, new Comparator<Pizza>() {  
    @Override  
    public int compare(Pizza p1, Pizza p2) {  
        return new CompareToBuilder().append(p1.size, p2.size).append(p1.nrOfToppings, p2.nrOfToppings).append(p1.name, p2.name).toComparison();  
    }  
});  

Like Guavaโ€™s ComparisonChain, this library class sorts easily on multiple fields, but also defines default behavior for null values (ie. 1, a, b, z, null). However, you canโ€™t specify anything else either, unless you provide your own Comparator.

Again, as noted in the comments below, these getters are all evaluated immediately for each comparison.

Thus

Ultimately it comes down to flavor and the need for flexibility (Guavaโ€™s ComparisonChain) vs. concise code (Apacheโ€™s CompareToBuilder).

Bonus method

I found a nice solution that combines multiple comparators in order of priority on CodeReview in a MultiComparator:

class MultiComparator<T> implements Comparator<T> {
    private final List<Comparator<T>> comparators;

    public MultiComparator(List<Comparator<? super T>> comparators) {
        this.comparators = comparators;
    }

    public MultiComparator(Comparator<? super T>... comparators) {
        this(Arrays.asList(comparators));
    }

    public int compare(T o1, T o2) {
        for (Comparator<T> c : comparators) {
            int result = c.compare(o1, o2);
            if (result != 0) {
                return result;
            }
        }
        return 0;
    }

    public static <T> void sort(List<T> list, Comparator<? super T>... comparators) {
        Collections.sort(list, new MultiComparator<T>(comparators));
    }
}

Ofcourse Apache Commons Collections has a util for this already:

ComparatorUtils.chainedComparator(comparatorCollection)

Collections.sort(list, ComparatorUtils.chainedComparator(comparators));
2 of 15
156

Do you see anything wrong with the code?

Yes. Why are you adding the three fields together before you compare them?

I would probably do something like this: (assuming the fields are in the order you wish to sort them in)

@Override public int compare(final Report record1, final Report record2) {
    int c;
    c = record1.getReportKey().compareTo(record2.getReportKey());
    if (c == 0)
       c = record1.getStudentNumber().compareTo(record2.getStudentNumber());
    if (c == 0)
       c = record1.getSchool().compareTo(record2.getSchool());
    return c;
}
๐ŸŒ
DevGenius
blog.devgenius.io โ€บ sorting-an-array-of-object-by-multiple-fields-in-java-and-javascript-e66f0366fc71
Sorting an Array of Objects by Multiple Fields in Java and JavaScript | by Pratiyush Prakash | Dev Genius
July 6, 2025 - Letโ€™s say we have an array of Employee objects. Where Employee is a class with two field (name and salary). First problem is to sort the array based on salary. This I am assuming we all know. So we can do something like this. // let's assume we have an array of Employee - employees // Employee is a class of two fields (String name, int salary)Arrays.sort(employees, (a,b) -> a.salary - b.salary); Second problem is to sort the array based on salary and then name.
Find elsewhere
๐ŸŒ
How to do in Java
howtodoinjava.com โ€บ home โ€บ java sorting โ€บ java collections sort()
Java Collections sort() - HowToDoInJava
December 14, 2022 - In the above code examples, we learned to sort an ArrayList in default order or reverse order. We also learned to use the Comparators for implementing the custom sorting logic. Happy Learning !! Sort a String ยท Sort an Array ยท Sort List of Objects ยท Collections.sort() Comparator.theComparing() Sort Map by values ยท Sort Map by key ยท Sort on multiple fields ยท Lokesh Gupta ยท A fun-loving family man, passionate about computers and problem-solving, with over 15 years of experience in Java and related technologies.
๐ŸŒ
BeginnersBook
beginnersbook.com โ€บ 2013 โ€บ 12 โ€บ java-arraylist-of-object-sort-example-comparable-and-comparator
Java ArrayList of Object Sort Example (Comparable And Comparator)
And I want to have an ArrayList of Student Object, which can be defined like this: import java.util.*; public class ArrayListSorting { public static void main(String args[]){ ArrayList<Student> arraylist = new ArrayList<Student>(); arraylist.add(new Student(223, "Chaitanya", 26)); arraylist.add(new Student(245, "Rahul", 24)); arraylist.add(new Student(209, "Ajeet", 32)); Collections.sort(arraylist); for(Student str: arraylist){ System.out.println(str); } } }
๐ŸŒ
Java67
java67.com โ€บ 2021 โ€บ 09 โ€บ java-comparator-multiple-fields-example.html
How to sort a List or Stream by Multiple Fields in Java? Comparator comparing() + thenComparing Example | Java67
If your natural ordering requires multiple fields comparing then go for it, otherwise use a Comparator. In general, the code for sorting which defines natural order is implemented using Comparable and resides in the same class but Comparator ...
๐ŸŒ
Makeinjava
makeinjava.com โ€บ home โ€บ sort objects on multiple fields /properties โ€“ comparator interface (lambda stream java 8)
Sort object on multiple fields/properties-Comparator (lamda stream java8)
January 3, 2024 - Comparator to sort objects by age. package org.learn; import java.util.ArrayList; import java.util.Comparator; import java.util.List; public class SortObjectByField { public static void main(String[] args) { List <Person> personList = new ArrayList<>(); personList.add(new Person("Mike", "harvey", 34, "001894536")); personList.add(new Person("Nick", "young", 75, "005425676")); personList.add(new Person("Jack", "slater", 21 ,"009654153")); personList.add(new Person("gary", "hudson", 55,"00564536")); personList.add(new Person("Mike", "harvey", 21 ,"003685417")); personList.add(new Person("gary", "hudson", 25,"00452341")); System.out.println("1.
๐ŸŒ
Team Treehouse
teamtreehouse.com โ€บ community โ€บ java-compareto-sorting-sorting-multiple-fields-for-same-object
Java CompareTo Sorting - Sorting Multiple Fields for Same Object (Example) | Treehouse Community
September 14, 2017 - public class Player implements Comparable<Player> @Override public int compareTo(Player object) { Player other = (Player) object; // We always want to sort by last name then first name if(equals(other)) { return 0; } return lastName.compareTo(other.lastName); } Collections.sort(team.getPlayerList()); Android Development Techdegree Graduate 27,137 Points ... I figured this out, I needed to utilize comparators. Here is a good resource: https://beginnersbook.com/2013/12/java-arraylist-of-object-sort-example-comparable-and-comparator/
๐ŸŒ
YouTube
youtube.com โ€บ improve your programming skills
Sort a list of objects by two fields in Java - YouTube
We have a list of Employee objects(name; birthYear). This video show you how to sort those objects by name, then by age
Published: October 25, 2016
Views: 17K
๐ŸŒ
amitph
amitph.com โ€บ home โ€บ java โ€บ sorting collection of objects by multiple fields in java
Sorting Collection of Objects by Multiple Fields in Java - amitph
February 10, 2026 - Implement custom Comparators to handle sorting logic for your custom Java Objects easily. Googleโ€™s Guava and Apache Commons libraries offer abstractions like ComparisonChain and CompareToBuilder to simplify multi-field comparisons.
๐ŸŒ
Javaprogramto
javaprogramto.com โ€บ 2020 โ€บ 08 โ€บ java-8-sorting-stream-on-multiple-fields.html
Java 8 โ€“ Sorting Stream On Multiple Fields with Comparator.thenComparing()
Step-by-step Java tutorials, programs, and interview questions with clear explanations for beginners and pros. ... In this tutorial, You'll learn how to sort the collection or stream of objects on multiple fields in java 8.
๐ŸŒ
How to do in Java
howtodoinjava.com โ€บ home โ€บ java sorting โ€บ java comparator thencomparing() example
Java Comparator thenComparing() Example - HowToDoInJava
August 30, 2022 - Example of using thenComparing() to create Comparator which is capable of sorting by multiple fields. private static ArrayList<Employee> getUnsortedEmployeeList() { ArrayList<Employee> list = new ArrayList<>(); list.add( new Employee(2, "Lokesh", "Gupta") ); list.add( new Employee(1, "Alex", "Gussin") ); list.add( new Employee(4, "Brian", "Sux") ); list.add( new Employee(5, "Neon", "Piper") ); list.add( new Employee(3, "David", "Beckham") ); list.add( new Employee(7, "Alex", "Beckham") ); list.add( new Employee(6, "Brian", "Suxena") ); return list; } ArrayList<Employee> employees = getUnsortedEmployeeList(); //Compare by first name and then last name Comparator<Employee> compareByName = Comparator .comparing(Employee::getFirstName) .thenComparing(Employee::getLastName); Collections.sort(employees, compareByName);
Top answer
1 of 15
293

You can use Collections.sort as follows:

private static void order(List<Person> persons) {

    Collections.sort(persons, new Comparator() {

        public int compare(Object o1, Object o2) {

            String x1 = ((Person) o1).getName();
            String x2 = ((Person) o2).getName();
            int sComp = x1.compareTo(x2);

            if (sComp != 0) {
               return sComp;
            } 

            Integer x1 = ((Person) o1).getAge();
            Integer x2 = ((Person) o2).getAge();
            return x1.compareTo(x2);
    }});
}

List<Persons> is now sorted by name, then by age.

String.compareTo "Compares two strings lexicographically" - from the docs.

Collections.sort is a static method in the native Collections library. It does the actual sorting, you just need to provide a Comparator which defines how two elements in your list should be compared: this is achieved by providing your own implementation of the compare method.

2 of 15
204

For those able to use the Java 8 streaming API, there is a neater approach that is well documented here: Lambdas and sorting

I was looking for the equivalent of the C# LINQ:

.ThenBy(...)

I found the mechanism in Java 8 on the Comparator:

.thenComparing(...)

So here is the snippet that demonstrates the algorithm.

    Comparator<Person> comparator = Comparator.comparing(person -> person.name);
    comparator = comparator.thenComparing(Comparator.comparing(person -> person.age));

Check out the link above for a neater way and an explanation about how Java's type inference makes it a bit more clunky to define compared to LINQ.

Here is the full unit test for reference:

@Test
public void testChainedSorting()
{
    // Create the collection of people:
    ArrayList<Person> people = new ArrayList<>();
    people.add(new Person("Dan", 4));
    people.add(new Person("Andi", 2));
    people.add(new Person("Bob", 42));
    people.add(new Person("Debby", 3));
    people.add(new Person("Bob", 72));
    people.add(new Person("Barry", 20));
    people.add(new Person("Cathy", 40));
    people.add(new Person("Bob", 40));
    people.add(new Person("Barry", 50));

    // Define chained comparators:
    // Great article explaining this and how to make it even neater:
    // http://blog.jooq.org/2014/01/31/java-8-friday-goodies-lambdas-and-sorting/
    Comparator<Person> comparator = Comparator.comparing(person -> person.name);
    comparator = comparator.thenComparing(Comparator.comparing(person -> person.age));

    // Sort the stream:
    Stream<Person> personStream = people.stream().sorted(comparator);

    // Make sure that the output is as expected:
    List<Person> sortedPeople = personStream.collect(Collectors.toList());
    Assert.assertEquals("Andi",  sortedPeople.get(0).name); Assert.assertEquals(2,  sortedPeople.get(0).age);
    Assert.assertEquals("Barry", sortedPeople.get(1).name); Assert.assertEquals(20, sortedPeople.get(1).age);
    Assert.assertEquals("Barry", sortedPeople.get(2).name); Assert.assertEquals(50, sortedPeople.get(2).age);
    Assert.assertEquals("Bob",   sortedPeople.get(3).name); Assert.assertEquals(40, sortedPeople.get(3).age);
    Assert.assertEquals("Bob",   sortedPeople.get(4).name); Assert.assertEquals(42, sortedPeople.get(4).age);
    Assert.assertEquals("Bob",   sortedPeople.get(5).name); Assert.assertEquals(72, sortedPeople.get(5).age);
    Assert.assertEquals("Cathy", sortedPeople.get(6).name); Assert.assertEquals(40, sortedPeople.get(6).age);
    Assert.assertEquals("Dan",   sortedPeople.get(7).name); Assert.assertEquals(4,  sortedPeople.get(7).age);
    Assert.assertEquals("Debby", sortedPeople.get(8).name); Assert.assertEquals(3,  sortedPeople.get(8).age);
    // Andi     : 2
    // Barry    : 20
    // Barry    : 50
    // Bob      : 40
    // Bob      : 42
    // Bob      : 72
    // Cathy    : 40
    // Dan      : 4
    // Debby    : 3
}

/**
 * A person in our system.
 */
public static class Person
{
    /**
     * Creates a new person.
     * @param name The name of the person.
     * @param age The age of the person.
     */
    public Person(String name, int age)
    {
        this.age = age;
        this.name = name;
    }

    /**
     * The name of the person.
     */
    public String name;

    /**
     * The age of the person.
     */
    public int age;

    @Override
    public String toString()
    {
        if (name == null) return super.toString();
        else return String.format("%s : %d", this.name, this.age);
    }
}
๐ŸŒ
Medium
bindushrestha.medium.com โ€บ how-to-order-list-of-objects-using-multiple-fields-b0b67c610613
How to sort list of objects using multiple fields? | by Bindu Shrestha | Medium
May 10, 2022 - private List<Student> sortWithLambdaExp(List<Student> list) {// sort using stream and firstNamelist.sort(Comparator.comparing((Student s) -> s.getStream()).thenComparing((Student s) -> s.getFirstName()));return list;}