Sort a List of objects by multiple attributes in Java
This post will discuss how to sort a list of objects by multiple attributes in Java.
1. Using Comparator
You can implement a custom Comparator to sort a list by multiple attributes. A Comparator can be passed to Collections.sort() or List.sort() method to allow control over the sort order. i.e., it defines how two items in the list should be compared.
For example, the following code creates a list of Student and in-place sorts it based on the name. If two objects have the same name, their ordering is decided by age. You can pass a method reference to the Comparator.comparing(), and it will extract and returns a comparator based on that function. To sort on multiple attributes, use Comparator.thenComparing() to combine two comparisons.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
import java.util.Arrays; import java.util.Comparator; import java.util.List; class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } } public class Main { public static void main(String[] args) { List<Student> students = Arrays.asList( new Student("John", 25), new Student("Akon", 15), new Student("John", 20), new Student("Tony", 10) ); // Java 7 and before /* Collections.sort(students, new Comparator<>() { @Override public int compare(Student o1, Student o2) { int cmp = o1.getName().compareTo(o2.getName()); if (cmp != 0) { return cmp; } return Integer.valueOf(o1.getAge()).compareTo(o2.getAge()); } });*/ // Java 8 and above /* // Using lambda expressions students.sort((o1, o2) -> { int cmp = o1.getName().compareTo(o2.getName()); if (cmp != 0) { return cmp; } return Integer.valueOf(o1.getAge()).compareTo(o2.getAge()); });*/ // Using Comparator.comparing() method students.sort(Comparator.comparing(Student::getName) .thenComparing(Student::getAge)); for (Student student : students) { System.out.println(student); } } } |
Output:
Student{name=’Akon’, age=15}
Student{name=’John’, age=20}
Student{name=’John’, age=25}
Student{name=’Tony’, age=10}
If you prefer the Guava library, you can construct a Comparator using ComparisonChain to perform a chained comparison to facilitate sorting on multiple attributes, as shown below:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
import com.google.common.collect.ComparisonChain; import java.util.*; class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } } public class Main { public static void main(String[] args) { List<Student> students = Arrays.asList( new Student("John", 25), new Student("Akon", 15), new Student("John", 20), new Student("Tony", 10) ); Collections.sort(students, new Comparator<>() { @Override public int compare(Student o1, Student o2) { return ComparisonChain.start() .compare(o1.getName(), o2.getName()) .compare(o1.getAge(), o2.getAge()) .result(); } }); // Java 8 and above: /* Collections.sort(students, (o1, o2) -> ComparisonChain.start() .compare(o1.getName(), o2.getName()) .compare(o1.getAge(), o2.getAge()) .result()); */ for (Student student : students) { System.out.println(student); } } } |
Output:
Student{name=’Akon’, age=15}
Student{name=’John’, age=20}
Student{name=’John’, age=25}
Student{name=’Tony’, age=10}
Similar to Guava’s ComparisonChain, you may use the CompareToBuilder class of the Apache Commons Lang library.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
import org.apache.commons.lang3.builder.CompareToBuilder; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } } public class Main { public static void main(String[] args) { List<Student> students = Arrays.asList( new Student("John", 25), new Student("Akon", 15), new Student("John", 20), new Student("Tony", 10) ); Collections.sort(students, new Comparator<>() { @Override public int compare(Student p1, Student p2) { return new CompareToBuilder() .append(p1.getName(), p2.getName()) .append(p1.getAge(), p2.getAge()) .toComparison(); } }); // Java 8 and above: /* Collections.sort(students, (p1, p2) -> new CompareToBuilder() .append(p1.getName(), p2.getName()) .append(p1.getAge(), p2.getAge()) .toComparison()); */ for (Student student : students) { System.out.println(student); } } } |
Output:
Student{name=’Akon’, age=15}
Student{name=’John’, age=20}
Student{name=’John’, age=25}
Student{name=’Tony’, age=10}
2. Implement Comparable Interface
If an object implements the Comparable interface, you can sort a list of that object using Collections.sort() or List.sort() method. This class’s implementer needs to override the abstract method compareTo(), which compares the object with the specified object. The value returned by the compareTo() decides the position of the object relative to the specified object.
For example, the following code creates a list of Student objects, where Student implements the Comparable interface and the compareTo() method orders elements by name and then by age.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
import java.util.Arrays; import java.util.Collections; import java.util.List; class Student implements Comparable<Student> { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int compareTo(Student o) { int cmp = this.getName().compareTo(o.getName()); if (cmp != 0) { return cmp; } return Integer.valueOf(this.getAge()).compareTo(o.getAge()); } } public class Main { public static void main(String[] args) { List<Student> students = Arrays.asList( new Student("John", 25), new Student("Akon", 15), new Student("John", 20), new Student("Tony", 10) ); Collections.sort(students); for (Student student : students) { System.out.println(student); } } } |
Output:
Student{name=’Akon’, age=15}
Student{name=’John’, age=20}
Student{name=’John’, age=25}
Student{name=’Tony’, age=10}
3. Using Stream API
If you need a new sorted list, without modifying the original list, the best option is to use Java 8 Stream API. The idea is to get a stream consisting of the elements of the list, sort it with the sorted() method using comparing comparator, and finally collect all sorted elements in a list.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
import java.util.Arrays; import java.util.Comparator; import java.util.List; class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } } public class Main { public static void main(String[] args) { List<Student> students = Arrays.asList( new Student("John", 25), new Student("Akon", 15), new Student("John", 20), new Student("Tony", 10) ); students.stream() .sorted(Comparator.comparing(Student::getName) .thenComparing(Student::getAge)) .forEach(System.out::println); } } |
Output:
Student{name=’Akon’, age=15}
Student{name=’John’, age=20}
Student{name=’John’, age=25}
Student{name=’Tony’, age=10}
That’s all about sorting a list of objects by multiple attributes in Java.
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)