Lambda 实现超强排序
发布日期:2025-04-04 00:40:15 浏览次数:6 分类:精选文章

本文共 3176 字,大约阅读时间需要 10 分钟。

在系统开发过程中,数据排序是频繁遇到的场景。传统方法是通过存储系统的排序功能或在内存中直接排序。如今,我们将重点探讨第二种在内存中进行排序的方法,并结合Java8的新特性,详细阐述各种排序实现方式。

基础类定义

首先,我们定义了一个基础类 Student,该类将作为排序的模型。该类包含了两个字段:nameage,并提供了 equalshashCode 方法以确保对象的唯一性和一致性。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private String name;
private int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}

基于Comparator排序

在Java8之前,我们通常通过实现Comparator接口来排序数据。例如,以下是一个匿名内部类的实现:

Comparator
comparator = new Comparator
() {
@Override
public int compare(Student h1, Student h2) {
return h1.getName().compareTo(h2.getName());
}
};
Collections.sort(students, comparator);

这种方法虽然简单,但在支持复杂排序逻辑时相对不够灵活。我们可以通过Lambda表达式将其简化:

Collections.sort(students, (h1, h2) -> h1.getName().compareTo(h2.getName()));

或者,对于更通用的使用,可以定义一个静态方法来实现特定的排序逻辑:

public static int compareByNameThenAge(Student s1, Student s2) {
if (s1.name.equals(s2.name)) {
return Integer.compare(s1.age, s2.age);
} else {
return s1.name.compareTo(s2.name);
}
}
Collections.sort(students, Student::compareByNameThenAge);

使用Comparator的comparing方法

从Java8开始,Comparator类增加了新的comparing方法,可以将传入的Function参数作为排序依据。例如,可以直接使用:

Comparator.comparing(Student::getName)

如果需要多级排序,可以使用thenComparing方法:

Comparator.comparing(Student::getName).thenComparing(Student::age)

这种方法简化了排序逻辑,同时非常直观。

多条件排序

有时候,我们需要对多个字段进行排序。例如,首先按名字排序,若名字相同,则按年龄排序。可以在Comparator中使用thenComparing方法实现:

Comparator.comparing(Student::getName).thenComparing(Student::age)

这种方法的灵活性和简洁性远远超过传统的匿名内部类实现。

在Stream中进行排序

在Java8引入的Stream API中,也支持排序操作。通过将集合流转换为排序流,再收集到结果集合中:

List
sortedStudents = students.stream()
.sorted(comparator)
.collect(Collectors.toList());

同样可以使用Lambda表达式:

students.stream()
.sorted((h1, h2) -> h1.getName().compareTo(h2.getName()))
.collect(Collectors.toList());

倒序排列

对于倒序排列,可以通过将比较逻辑取反实现。例如:

Comparator reverseComparator = (h1, h2) -> h2.getName().compareTo(h1.getName());
Collections.sort(students, reverseComparator);

或者,直接使用Comparator.reversed()方法:

Collections.sort(students, Comparator.reverseOrder());

对于名字字段进行倒序排列:

Comparator.comparing(Student::getName, Comparator.reverseOrder());

处理null值

在实际应用中,列表中可能包含null值,或者排序的字段可能为null。为了安全排序,需要处理null值。Java8已提供了Comparator.nullsLastComparator.nullsFirst方法来处理这种情况。

例如,null值排在结尾:

Comparator.nullsLast(Comparator.comparing(Student::getName))

null值排在开头:

Comparator.nullsFirst(Comparator.comparing(Student::getName))

为了处理排序条件字段为null的情况,可以使用双重Comparator.nullsLast

Comparator.nullsLast(
Comparator.nullsLast(
Comparator.comparing(Student::getName, Comparator.nullsLast(Comparator.naturalOrder()))
)
)

这种方法允许我们在复杂场景下安全排序数据。

总结

通过对Java8中内存排序的全面探讨,我们掌握了多种排序实现方式。从传统的Comparator接口到现代的Lambda表达式,再到StreamAPI和倒序排列,以及处理null值的方法,这些方法为我们提供了灵活高效的数据排序工具。无论是基础场景还是复杂逻辑,这些方法都能满足我们的需求。

上一篇:Lambda 表达式(使用前提、“类型推断”、作用、优缺点、Lambda还能省略的情况)【java8新特性------Lambda 表达式】
下一篇:lambda 与列表理解性能

发表评论

最新留言

很好
[***.229.124.182]2025年04月20日 09时35分31秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章