实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student{
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 国籍
*/
private String nationality;
}
测试数据
List<Student> students = new ArrayList<>();
Student student1 = new Student("java", 22, "Chinese");
Student student2 = new Student("go", 11, "USA");
Student student3 = new Student("js", 20, "Japan");
Student student4 = new Student("python", 16, "Thailand");
Student student5 = new Student("php", 33, "Chinese");
Student student6 = new Student("php", 16, "Chinese");
Student student7 = new Student("java", 16, "Thailand");
students.add(student1);
students.add(student2);
students.add(student3);
students.add(student4);
students.add(student5);
students.add(student6);
students.add(student7);
1、自定义实体类继承Comparable重写compareTo方法(自然排序)
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student implements Comparable<Student>{
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 国籍
*/
private String nationality;
/**
*
* @param student
* @return
* 如果返回值为负数:当前对象大
* 如果返回值为正数:当前对象小
* 如果返回值为0:一样大
*/
@Override
public int compareTo(Student student) {
// lombok已经重写equals方法,字段都相等时对象才相等
if (this.equals(student)) {
return 0;
}
int ageCompare = Integer.compare(this.age, student.age);
if (ageCompare != 0) {
return ageCompare;
}
int nationalityCompare = this.nationality.compareTo(student.nationality);
if (nationalityCompare != 0) {
return nationalityCompare;
}
return this.name.compareTo(student.name);
}
}
测试
// 先根据年龄从小到大,再根据国籍从小到大,最后根据姓名从小到大
Collections.sort(students);
students.forEach(System.out::println);
结果
Student(name=go, age=11, nationality=USA)
Student(name=php, age=16, nationality=Chinese)
Student(name=java, age=16, nationality=Thailand)
Student(name=python, age=16, nationality=Thailand)
Student(name=js, age=20, nationality=Japan)
Student(name=java, age=22, nationality=Chinese)
Student(name=php, age=33, nationality=Chinese)
注:想要从大到小的排序,只需将实体类的重写方法compareTo中的this和student互换位置;也可以在前面加一个负号,如-Integer.compare(this.age, student.age)。
2、如果Student为引用依赖的类,无法修改时(Comparator定制排序)
students.sort(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
if (o1.equals(o2)) {
return 0;
}
int ageCompare = Integer.compare(o1.getAge(), o2.getAge());
if (ageCompare != 0) {
return ageCompare;
}
int nationalityCompare = o1.getNationality().compareTo(o2.getNationality());
if (nationalityCompare != 0) {
return nationalityCompare;
}
return o1.getName().compareTo(o2.getName());
}
});
注:匿名内部类可使用lambda简写方式
集合过滤部分数据再排序,需要使用stream流+Comparator定制排序
stream常用的方法(https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html)
修饰符和类型 | 方法及说明 |
long | count() 返回此流中元素的计数。 |
Stream<T> | distinct() 返回由该流的不同元素(根据 Object.equals(Object))组成的流。 |
Stream<T> | filter(Predicate<? super T> predicate) 返回一个流,该流由与给定谓词匹配的此流的元素组成。 |
void | forEach(Consumer<? super T> action) 对此流的每个元素执行一个操作。 |
Stream<T> | limit(long maxSize) 返回由该流的元素组成的流,被截断为不超过maxSize长度。 |
<R> Stream<R> | map(Function<? super T,? extends R> mapper) 返回一个流,该流由将给定函数应用于此流的元素的结果组成。 |
Optional<T> | max(Comparator<? super T> comparator) 返回此流的最大元素 。 |
Optional<T> | min(Comparator<? super T> comparator) 返回此流的最小元素 。 |
Stream<T> | skip(long n) 在丢弃流的前 n 个元素后,返回由该流的剩余元素组成的流。 |
Stream<T> | sorted() 返回一个流,该流由该流的元素组成,并按自然顺序排序。 |
Stream<T> | sorted(Comparator<? super T> comparator) 返回一个流,该流由该流的元素组成,并根据提供的排序Comparator。 |
students.stream()
// 学生年龄大于16岁
.filter(student -> student.getAge() >= 16)
.sorted((Student o1, Student o2) -> {
if (o1.equals(o2)) {
return 0;
}
int ageCompare = Integer.compare(o1.getAge(), o2.getAge());
if (ageCompare != 0) {
return ageCompare;
}
int nationalityCompare = o1.getNationality().compareTo(o2.getNationality());
if (nationalityCompare != 0) {
return nationalityCompare;
}
return o1.getName().compareTo(o2.getName());
})
.forEach(System.out::println);
结果
Student(name=php, age=16, nationality=Chinese)
Student(name=java, age=16, nationality=Thailand)
Student(name=python, age=16, nationality=Thailand)
Student(name=js, age=20, nationality=Japan)
Student(name=java, age=22, nationality=Chinese)
Student(name=php, age=33, nationality=Chinese)
4、Comparator与Comparable区别
推荐使用Comparator,无需修改实体类结构,可以降低耦合度
Comparable只能给定一种排序规则,Comparator可以编写多个类多个排序规则,更灵活