原代码如下,一开始,没有看懂sorted方法是如何根据年龄降序排列的
public class Stream_sorted {
public static void main(String[] args) {
List<Test> list = new ArrayList<>();
list.add(new Test("张三",23,new BigDecimal("3000"),new BigDecimal("1.1")));
list.add(new Test("李四",24,new BigDecimal("2800"),new BigDecimal("1.2")));
list.add(new Test("王五",22,new BigDecimal("3200"),new BigDecimal("1.3")));
//根据年龄从大到小排序
list = list.stream()
.sorted(Comparator.comparing(Test::getAge).reversed())
.collect(Collectors.toList());
list.forEach(System.out::println);
}
}
Comparator.comparing(Test::getAge)
Comparator.comparing()
是一个静态方法,用于创建一个比较器。Test::getAge
是一个方法引用,它指向Test
类的getAge()
方法。
结合起来,Comparator.comparing(Test::getAge)
创建了一个比较器,用于比较 Test
对象based on their age。这个表达式的作用相当于下面的lambda表达式:
Comparator.comparing((Test t) -> t.getAge())
或者等价于传统的比较器实现:
new Comparator<Test>() {
@Override
public int compare(Test t1, Test t2) {
return Integer.compare(t1.getAge(), t2.getAge());
}
}
这种方式的优点包括:
- 代码更简洁,可读性更高。
- 直接指定了用于比较的字段(在这个case中是age),减少了出错的可能。
- 可以很容易地进行链式操作,比如反转顺序(如代码中的
.reversed()
)。
.reversed()
.reversed()
是 Java 8 中 Comparator
接口的一个默认方法。这个方法的作用是创建并返回一个比较器,它与原比较器的顺序相反。
- 功能:
- 它会反转原始比较器的排序顺序。
- 如果原始顺序是升序(从小到大),
.reversed()
会使其变为降序(从大到小),反之亦然。
- 使用场景:
.sorted(Comparator.comparing(Test::getAge).reversed())
-
Comparator.comparing(Test::getAge)
创建了一个按年龄升序排列的比较器。- 调用
.reversed()
将这个比较器转换为按年龄降序排列。
- 工作原理:
- 如果原始比较器对于两个元素 a 和 b 返回一个负数(表示 a < b),
- 那么反转后的比较器会返回一个正数(表示 a > b)。
- 等价实现: 如果不使用
.reversed()
,这样可以实现相同的效果: -
.sorted((t1, t2) -> t2.getAge().compareTo(t1.getAge()))
或者
-
.sorted(Comparator.comparing(Test::getAge, Comparator.reverseOrder()))
- 优点:
- 代码更简洁、更易读。
- 可以轻松地在升序和降序之间切换,而不需要重写整个比较逻辑。
- 与其他
Comparator
方法良好集成,支持方法链。
- 注意事项:
- 调用
.reversed()
会创建一个新的Comparator
对象,原始的比较器不会被修改。 - 连续两次调用
.reversed()
会得到一个等同于原始比较器的新比较器。
- 调用
list.forEach(System.out::println)
list.forEach()
:forEach
是 Java 8 中添加到 Iterable 接口的一个默认方法。- 它接受一个 Consumer 函数式接口作为参数。
- 这个方法会遍历集合中的每个元素,并对每个元素执行指定的操作。
System.out::println
:- 这是一个方法引用,指向
System.out
对象的println
方法。 - 方法引用是 Java 8 引入的一种简洁表示 lambda 表达式的方式。
- 这是一个方法引用,指向
这行代码等价于以下几种写法:
- 使用 lambda 表达式:
list.forEach(item -> System.out.println(item));
2.使用匿名内部类:
list.forEach(new Consumer<Test>() {
@Override
public void accept(Test item) {
System.out.println(item);
}
});
3.使用传统的 for-each 循环:
for (Test item : list) {
System.out.println(item);
}
使用 forEach
和方法引用的优点:
- 代码更简洁、更易读。
- 符合函数式编程风格,使代码更具声明性。
- 可以很容易地与其他 Stream 操作结合使用。