How to sort Java objects
object order
Direct comparison leads to ClassCastException
import lombok.AllArgsConstructor; import lombok.Data; import java.util.*; /** * @author niushuai * @date 2019/9/18 10:17 */ public class CompareDemo { public static void main(String[] args) { Student s1 = new Student("Zhang three 1", 13); Student s2 = new Student("Zhang three 2", 12); Student s3 = new Student("Zhang three 3", 11); arraysDemo(s1, s2, s3); } public static void arraysDemo(Student s1, Student s2, Student s3) { Student[] students = new Student[3]; students[0] = s1; students[1] = s2; students[2] = s3; Arrays.sort(students); System.out.println(Arrays.toString(students)); } } @Data @AllArgsConstructor class Student { private String name; private int age; }
If this is the case, it will directly lead to the following situation.
Looking at the exception information, you can see that Student cannot be converted to Comparable, which indicates that our Student class needs to implement Comparable interface. So let's try to implement Comparable interface.
Using Comparable Interface
I sort it here by age, so when implementing the compareTo method, I compare values by age field.
import lombok.AllArgsConstructor; import lombok.Data; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; /** * @author niushuai * @date 2019/9/18 10:17 */ public class CompareDemo { public static void main(String[] args) { Student s1 = new Student("Zhang three 1", 13); Student s2 = new Student("Zhang three 2", 12); Student s3 = new Student("Zhang three 3", 11); arraysDemo(s1, s2, s3); System.out.println("--------------------------------------------------------------------------------------------"); listDemo(s1, s2, s3); } public static void listDemo(Student s1, Student s2, Student s3) { List<Student> students = new ArrayList<Student>(); students.add(s1); students.add(s2); students.add(s3); System.out.println("Before sorting:"+students); Collections.sort(students); System.out.println("After sorting:"+students); } public static void arraysDemo(Student s1, Student s2, Student s3) { Student[] students = new Student[3]; students[0] = s1; students[1] = s2; students[2] = s3; System.out.println("Before sorting:"+Arrays.toString(students)); Arrays.sort(students); System.out.println("After sorting:"+Arrays.toString(students)); } } @Data @AllArgsConstructor class Student implements Comparable<Student> { private String name; private int age; @Override public int compareTo(Student o) { int result = 0; int targetAge = o.getAge(); int thisAge = this.getAge(); if (thisAge > targetAge) { result = 1; } else if (thisAge < targetAge) { result = -1; } return result; } }
Operation results:
So we can see that this sort of ordering happens according to our expected results.
Notes for Objects Stored in List
For objects stored in List, such as:
List<Student> students = new ArrayList<Student>(); Collections.sort(students);
There is an error in such code. The parameters received by the Collections.sort() method must implement the Comparable interface or use the form Collections. sort (students, new Comparable < Student >(){...} of anonymous internal classes).
Using anonymous inner classes
At the same time, we have another way to sort objects that do not implement the Comparable interface, which is to use anonymous inner classes.
By looking at the Arrays.sort() and Collections.sort() methods, we can see the following:
Arrays.sort(Object[] a) Arrays.sort(T[] a, Comparator<? super T> c) Collections.sort(List<T> list) Collections.sort(List<T> list, Comparator<? super T> c)
So we've found that both the sort methods provided by java can be implemented using anonymous inner classes, so let's test them in this way.
import lombok.AllArgsConstructor; import lombok.Data; import java.util.*; /** * @author niushuai * @date 2019/9/18 10:25 */ public class CompareDemo2 { public static void main(String[] args) { Student2 s1 = new Student2("Zhang three 1", 13); Student2 s2 = new Student2("Zhang three 2", 12); Student2 s3 = new Student2("Zhang three 3", 11); arraysDemo(s1, s2, s3); System.out.println("--------------------------------------------------------------------------------------------"); listDemo(s1, s2, s3); } public static void listDemo(Student2 s1, Student2 s2, Student2 s3) { List<Student2> students = new ArrayList<Student2>(); students.add(s1); students.add(s2); students.add(s3); System.out.println("Before sorting:"+students); Collections.sort(students, new Comparator<Student2>() { @Override public int compare(Student2 o1, Student2 o2) { return o1.getAge() - o2.getAge(); } }); System.out.println("After sorting:"+students); } public static void arraysDemo(Student2 s1, Student2 s2, Student2 s3) { Student2[] students = new Student2[3]; students[0] = s1; students[1] = s2; students[2] = s3; System.out.println("Before sorting:"+Arrays.toString(students)); Arrays.sort(students, new Comparator<Student2>() { @Override public int compare(Student2 o1, Student2 o2) { return o1.getAge() - o2.getAge(); } }); System.out.println("After sorting:"+Arrays.toString(students)); } } @Data @AllArgsConstructor class Student2 { private String name; private int age; }
Operation results:
We can see that the results of these two approaches are the same. So in both ways, the choice of QvQ depends entirely on personal will.