List排序的方法
List 排序方法:
1. list 的 sort()
package com.example.a;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
class User{
private Integer score;
private Integer age;
public User(Integer score, Integer age){
super();
this.score = score;
this.age = age;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
public class Demo {
public static void main(String[] args) {
List<User> users = new ArrayList<>();
users.add(new User(95, 26));
users.add(new User(84, 23));
users.add(new User(96, 25));
users.add(new User(95, 24));
// 单字段排序
users.sort(Comparator.comparing(User::getAge));
for(User user : users){
System.out.println(user.getScore() + "," + user.getAge());
}
System.out.println("---------------------------------");
// 多字段排序(法1)
users.sort((o1, o2) -> {
// 这里必须要在中间加分隔符。否则,若都是数字,会变成数字相加,再转为字符串
String tmp1 = o1.getScore() + ":" + o1.getAge();
String tmp2 = o2.getScore() + ":" + o2.getAge();
return tmp1.compareTo(tmp2);
});
for(User user : users){
System.out.println(user.getScore() + ":" + user.getAge());
}
System.out.println("---------------------------------");
// 多字段排序(法2)
users.sort((o1, o2) -> {
int i = o2.getScore() - o1.getScore();
if (i == 0) {
return o1.getAge() - o2.getAge();
}
return i;
});
for(User user : users){
System.out.println(user.getScore() + "," + user.getAge());
}
}
}
输出结果:
84,23 95,24 96,25 95,26 --------------------------------- 84:23 95:24 95:26 96:25 --------------------------------- 96,25 95,24 95,26 84,23
单字段排序:
在代码中,定义了 User
类包含 score
和 age
属性,创建了 ArrayList<User>
并添加了多个 User
对象实例。使用 users.sort(Comparator.comparing(User::getAge));
语句按照 age
字段对 users
列表进行排序。这里利用了 Comparator.comparing()
方法,它接收一个获取属性的函数式接口引用(此处为 User::getAge
,表示按照 User
对象的 age
属性进行比较),然后sort
方法会依据这个比较逻辑对列表元素进行排序。排序后通过循环打印出每个用户的 score
和 age
,结果展示了按照年龄从小到大排序后的用户信息。
多字段排序示例(法1):
使用自定义的比较逻辑,通过 lambda
表达式实现。在 lambda
表达式中,先将 User
对象的 score
和 age
组合成一个字符串(中间用:
分隔,是为了避免数字直接相加等问题,保证按预期拼接字符串用于比较),如 String tmp1 = o1.getScore() + ":" + o1.getAge();
,然后通过比较两个这样组合后的字符串大小(return tmp1.compareTo(tmp2);
)来确定元素的顺序,实现了多字段排序效果。
多字段排序示例(法2):
同样是用 lambda
表达式实现多字段排序。先比较 score
字段(int i = o2.getScore() - o1.getScore();
,通过差值判断大小,若差值为 0 则表示 score
相同),当 score
相同时,再比较 age
字段(return o1.getAge() - o2.getAge();
),最终返回比较结果来确定元素顺序,按照成绩降序、年龄升序(成绩相同时)的规则对列表进行了排序。
2. JDK8 的 stream 方法
2.1 对简单整数列表进行排序
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class StreamSortExample {
public static void main(String[] args) {
// 创建一个包含整数的ArrayList
List<Integer> numbers = new ArrayList<>();
numbers.add(5);
numbers.add(2);
numbers.add(8);
numbers.add(1);
// 使用Stream的sorted方法进行排序,并通过collect方法将结果收集回List
List<Integer> sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
System.out.println("排序后的整数列表: " + sortedNumbers);
}
}
在上述代码中:
2.1.1. 首先创建了一个ArrayList
,其中包含了几个整数元素;
2.1.2. 接着调用stream()
方法将List
转换为Stream
流,这样就能使用流相关的操作了;
2.1.3. 然后使用sorted()
方法,对于像Integer
这种基本数据类型对应的包装类(因为Stream
操作的是对象),它默认会按照自然顺序(在这里就是数字从小到大的顺序)对元素进行排序;
2.1.4. 最后使用collect(Collectors.toList())
将排序后的流元素收集回一个新的List
,并将其打印出来,运行结果会显示按照从小到大顺序排好的整数列表;
2.2 对自定义对象列表按照单个属性排序
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;
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class StreamSortExample {
public static void main(String[] args) {
// 创建一个包含Student对象的ArrayList
List<Student> students = new ArrayList<>();
students.add(new Student("Alice", 20));
students.add(new Student("Bob", 18));
students.add(new Student("Charlie", 22));
// 使用Stream的sorted方法结合Comparator按照年龄对学生列表进行排序
List<Student> sortedStudents = students.stream()
.sorted(Comparator.comparing(Student::getAge))
.collect(Collectors.toList());
// 打印排序后的学生列表信息
sortedStudents.forEach(student -> System.out.println("姓名: " + student.getName() + ", 年龄: " + student.getAge()));
}
}
在上述代码中:
2.2.1. 先定义了Student
类,包含name
和age
两个属性;
2.2.2. 创建了ArrayList<Student>
并添加了几个Student
实例;
2.2.3. 在使用Stream
进行排序时,调用sorted
方法并传入一个Comparator
,这里通过Comparator.comparing(Student::getAge)
来指定按照Student
对象的age
属性进行比较排序,也就是会按照年龄从小到大对学生列表进行排序;
2.1.4. 最后使用collect(Collectors.toList())
收集排序后的元素为新的列表,并且通过forEach
方法遍历打印出每个学生的姓名和年龄信息,展示排序后的结果;
2.3 对自定义对象列表按照多个属性排序
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class StreamSortExample {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student("Alice", 20));
students.add(new Student("Bob", 18));
students.add(new Student("Charlie", 20));
// 使用Stream的sorted方法结合Comparator按照年龄和姓名对学生列表进行排序
List<Student> sortedStudents = students.stream()
.sorted(Comparator.comparing(Student::getAge)
.thenComparing(Student::getName))
.collect(Collectors.toList());
sortedStudents.forEach(student -> System.out.println("姓名: " + student.getName() + ", 年龄: " + student.getAge()));
}
}
在上述代码中:
2.3.1. 创建了包含Student
对象的列表,其中有年龄相同的情况;
2.3.2. 调用sorted
方法时,传入的Comparator
通过链式调用thenComparing
来添加额外的比较条件。首先通过Comparator.comparing(Student::getAge)
按照年龄进行比较排序,然后使用.thenComparing(Student::getName)
表示在年龄相同的情况下,再按照姓名的字典顺序进行排序;
2.3.3. 最后同样收集排序后的元素为新列表并遍历打印出信息,展示按照多属性排序后的结果;
法3:Comparator 的 compare()
package org.example.a;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class User{
private int score;
private int age;
public User(int score, int age){
super();
this.score = score;
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Demo {
public static void main(String[] args) {
List<User> users = new ArrayList<User>();
users.add(new User(95, 26));
users.add(new User(84, 23));
users.add(new User(96, 25));
users.add(new User(95, 24));
Collections.sort(users, new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
int i = o2.getScore() - o1.getScore();
if(i == 0){
return o1.getAge() - o2.getAge();
}
return i;
}
});
for(User user : users){
System.out.println(user.getScore() + "," + user.getAge());
}
}
}
输出结果:
96,25 95,24 95,26 84,23
在上述代码中,ArrayList<User>
并添加了多个User
对象实例,然后使用Collections.sort(users, new Comparator<User>() {... });
来进行排序。这里Collections.sort()
方法接收要排序的列表以及一个 Comparator
接口的实现类实例(此处通过匿名内部类的方式实现)。在 compare
方法中,先比较 score
字段(通过差值判断大小,差值为 0 表示成绩相同),若成绩相同则比较age
字段,最后返回比较结果,按照成绩降序、年龄升序(成绩相同时)的规则对列表进行了排序,循环打印出排序后的用户信息展示了排序效果。
法4:Comparable 的 compareTo()
4.1 默认按增序排序:
package org.example.a;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Demo {
public static void main(String[] args) {
List<Integer> nums = new ArrayList<Integer>();
nums.add(3);
nums.add(5);
nums.add(1);
nums.add(0);
System.out.println(nums);
Collections.sort(nums);
System.out.println(nums);
}
}
输出结果:
[3, 5, 1, 0] [0, 1, 3, 5]
对于简单的 ArrayList<Integer>
,创建列表并添加元素后,直接调用Collections.sort(nums);
,由于Integer
类实现了 Comparable
接口,其内部的 compareTo
方法定义了默认的按照数字大小的增序排序逻辑,所以列表会按照从小到大的顺序被排序,从打印结果[3, 5, 1, 0]
和[0, 1, 3, 5]
可以看出排序前后的变化。
4.2 自定义对象排序示例:
package org.example.a;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class User implements Comparable<User>{
private int score;
private int age;
public User(int score, int age){
super();
this.score = score;
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(User o) {
int i = o.getScore() - this.getScore();
if(i == 0){
return this.getAge() - o.getAge();
}
return i;
}
}
public class Demo {
public static void main(String[] args) {
List<User> users = new ArrayList<User>();
users.add(new User(95, 26));
users.add(new User(84, 23));
users.add(new User(96, 25));
users.add(new User(95, 24));
Collections.sort(users);
for(User user : users){
System.out.println(user.getScore() + "," + user.getAge());
}
}
}
输出结果:
96,25 95,24 95,26 84,23
定义的 User
类实现了 Comparable<User>
接口,重写了 compareTo
方法。在 compareTo
方法中,先比较 score
字段(通过差值判断,不过这里是用 o.getScore() - this.getScore();
实现降序效果,差值为 0 表示成绩相同),若成绩相同则比较 age
字段(按照升序比较,return this.getAge() - o.getAge();
),最后返回比较结果。通过 Collections.sort(users);
对ArrayList<User>
进行排序,循环打印结果展示了按照成绩降序、年龄升序(成绩相同时)的规则排序后的用户信息。