In some special scenarios, we need to sort the List collection in the Java program. For example, get the List of all users from the third-party interface, but the List is sorted by user number from small to large by default, and our system needs to sort by user's age. At this time, we need to customize the List set.
There are three common methods for sorting lists:
- Use Comparable to sort;
- Sort using Comparator;
- For environments above JDK 8, you can also use Stream to sort.
Let's look at the specific implementation of various sorting methods.
1. Use Comparable sorting
According to the scenario designed in this article, we need to create a List set containing user lists and sort them according to the age of users. The specific implementation code is as follows:
public class ListSortExample { public static void main(String[] args) { // Create and initialize List List<Person> list = new ArrayList<Person>() {{ add(new Person(1, 30, "Beijing")); add(new Person(2, 20, "Xi'an")); add(new Person(3, 40, "Shanghai")); }}; // Sort using Comparable custom rules Collections.sort(list); // Print list set list.forEach(p -> { System.out.println(p); }); } } // The following set/get/toString uses lombok annotations @Getter @Setter @ToString class Person implements Comparable<Person> { private int id; private int age; private String name; public Person(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } @Override public int compareTo(Person p) { return p.getAge() - this.getAge(); } }
The execution result of the above code is shown in the following figure:
The core code of this method is as follows:
2. Sort using Comparator
Comparable is the comparison method inside the class, and comparator is the comparator outside the sorting class. To use comparator comparator, you do not need to modify the original Person class. You only need to expand a comparator of Person class. Comparator can be implemented in the following two ways:
- Create a Comparator comparator;
- Use Comparator anonymous class Comparator.
Among them, the second implementation method should be more concise. Let's observe the difference between the two through the following specific code.
2.1 create a Comparator
public class ListSortExample2 { public static void main(String[] args) { // Create and initialize List List<Person> list = new ArrayList<Person>() {{ add(new Person(1, 30, "Beijing")); add(new Person(2, 20, "Xi'an")); add(new Person(3, 40, "Shanghai")); }}; // Sorting with Comparator comparator Collections.sort(list, new PersonComparator()); // Print list set list.forEach(p -> { System.out.println(p); }); } } /** * New Person comparator */ class PersonComparator implements Comparator<Person> { @Override public int compare(Person p1, Person p2) { return p2.getAge() - p1.getAge(); } } @Getter @Setter @ToString class Person { private int id; private int age; private String name; public Person(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } }
The execution result of the above code is shown in the following figure:
The core implementation code of this method is as follows:
2.2 anonymous comparator
The Comparator comparator can use a more concise anonymous class to realize the sorting function. The specific implementation code is as follows:
public class ListSortExample2 { public static void main(String[] args) { // Create and initialize List List<Person> list = new ArrayList<Person>() {{ add(new Person(1, 30, "Beijing")); add(new Person(2, 20, "Xi'an")); add(new Person(3, 40, "Shanghai")); }}; // Sort using anonymous comparator Collections.sort(list, new Comparator<Person>() { @Override public int compare(Person p1, Person p2) { return p2.getAge() - p1.getAge(); } }); // Print list set list.forEach(p -> { System.out.println(p); }); } } @Getter @Setter @ToString class Person { private int id; private int age; private String name; public Person(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } }
The execution result of the above code is shown in the following figure:
3. Use Stream to sort
After JDK 8, a simpler method Stream flow can be used to realize the sorting function. Its implementation only needs one line of code. The specific implementation is as follows:
public class ListSortExample3 { public static void main(String[] args) { // Create and initialize List List<Person> list = new ArrayList<Person>() {{ add(new Person(1, 30, "Beijing")); add(new Person(2, 20, "Xi'an")); add(new Person(3, 40, "Shanghai")); }}; // Sorting using Stream list = list.stream().sorted(Comparator.comparing(Person::getAge).reversed()) .collect(Collectors.toList()); // Print list set list.forEach(p -> { System.out.println(p); }); } @Getter @Setter @ToString static class Person { private int id; private int age; private String name; public Person(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } } }
Where reversed() means reverse order. If this rule is not used, it is positive order.
The execution result of the above code is shown in the following figure:
Extension: sort field is null
When sorting with Stream, an exception will occur if a null value appears in the sorted field. The specific examples are as follows:
public class ListSortExample4 { public static void main(String[] args) { // Create and initialize List List<Person> list = new ArrayList<Person>() {{ add(new Person(30, "Beijing")); add(new Person(10, "Xi'an")); add(new Person(40, "Shanghai")); add(new Person(null, "Shanghai")); // Age is null }}; // In positive order of [age], but there is a null value in the age list = list.stream().sorted(Comparator.comparing(Person::getAge)) .collect(Collectors.toList()); // Print list set list.forEach(p -> { System.out.println(p); }); } } @Getter @Setter @ToString class Person { private Integer age; private String name; public Person(Integer age, String name) { this.age = age; this.name = name; } }
The execution result of the above code is shown in the following figure:
To solve the above problems, you need to give comparator Comparing passes the second parameter: comparator Nullsxxx, as shown in the following code:
public class ListSortExample4 { public static void main(String[] args) { // Create and initialize List List<Person> list = new ArrayList<Person>() {{ add(new Person(30, "Beijing")); add(new Person(10, "Xi'an")); add(new Person(40, "Shanghai")); add(new Person(null, "Shanghai")); }}; // In positive order of [age], but there is a null value in the age list = list.stream().sorted(Comparator.comparing(Person::getAge, Comparator.nullsFirst(Integer::compareTo))) .collect(Collectors.toList()); // Print list set list.forEach(p -> { System.out.println(p); }); } } @Getter @Setter @ToString class Person { private Integer age; private String name; public Person(Integer age, String name) { this.age = age; this.name = name; } }
Comparator.nullsFirst means to put the null value in the sorting field at the front of the collection. If you want to put the null value at the back of the collection, you can use comparator nullsLast.
The execution result of the above code is shown in the following figure:
summary
This paper introduces three List sorting methods. The first two methods are commonly used in versions before JDK 8. There are two ways to write the Comparator, which can be used in versions after JDK 8 Comparing implements sorting. If null values may appear in the sorting field, use Comparator Nullsxxx performs sorting processing (otherwise an error will be reported).
When the death comes, he will not be surprised, and he will not be angry without reason. Enjoy the joy of ordinary life, lifelong growth.
Blogger: post-80s programmers. Hobbies: reading, writing and jogging.
The official account: Java interview