目录
1 Comparator介绍
建议看英文文档
官方英文文档介绍
https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/Comparator.html
Comparator是一个函数式接口,因此可以用作 lambda 表达式或方法引用的赋值目标。它经常用于没有天然排序的集合进行排序,如 Collections.sort 或 Arrays.sort。或者对于某些有序数据结构的排序规则进行声明,如 TreeSet 、TreeMap 。也就是该接口主要用来进行集合排序。

1.1 函数式声明
函数式声明(Functional Declaration) 是指在Java中使用函数式编程的方式声明函数或方法。函数式编程是一种编程范式,它将计算视为函数应用的方式,强调了函数的纯粹性和不可变性。在Java中,函数式编程通常使用Lambda表达式、方法引用、函数接口等特性来实现。在你提供的代码中,Lambda表达式 (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1), keyExtractor.apply(c2)) 就是一个函数式声明,它表示一个比较器的定义,将对象的比较规则抽象为一个函数。
总之,comparing 方法是一个函数式编程的示例,它接受函数和比较器作为参数,然后返回一个基于提取的键值和键比较器的比较器,用于对象的排序。这种方式使得你可以轻松地基于对象的属性进行比较,而无需编写大量的比较逻辑。
1.2 简单的小案例
List<People> peoples = new ArrayList<>();
// 中间省略
// 按照年龄从小到大排序
peoples.sort(Comparator.comparing(People::getAge));
2. Comparator中的方法
Comparator 作为一个函数式接口只有一个抽象方法,但是它有很多的默认方法,我们来认识一下这些方法们。
2.1 compare 抽象方法
作为Comparator 唯一的抽象方法,int compare(T o1,T o2) 比较两个参数的大小, 返回负整数,零,正整数 ,分别代表 o1<o2、o1=o2、o1>o2,通常分别返回 -1、0 或 1。伪表达式:
// 输入两个同类型的对象 ,输出一个比较结果的int数字
(x1,x2)-> int
例子
自己动动手
public class SortedDemo {
public static void main(String[] args) {
List<String> words = Arrays.asList("watermelon","apple", "banana", "cherry");
// 使用比较器按字符串长度升序排序
words.sort((str2, str1) -> Integer.compare(str1.length(), str2.length()));
// words.sort((str2, str1) -> Integer.compare(str1.length(), str2.length()));//降序
System.out.println(words); // 输出: [apple, banana, cherry]
}
}
2.2 comparing方法
从 Java 8 开始,Comparator 提供了一系列的静态方法,并通过函数式的风格赋予 Comparator 更加强大和方便的功能,我们暂且称它们为 comparing系列方法。
重点介绍一下
comparing方法,以及它的源码实现。注意comparing方法有很多个不同的重载方法,这个是传入参数最全的方法介绍。
源码
public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}
参考解释
该方法是该系列方法的基本方法。是不是看上去很难懂的样子?我们来分析一下该方法。它一共两个参数都是函数式接口。
第一个参数 Function<? super T, ? extends U> keyExtractor 表示输入一个是 T 类型对象,输出一个 U 类型的对象,举个例子,输入一个 People 对象返回其年龄 Integer 数值:
// people -> people.getAge(); 转换为下面方法引用
Function<People, Integer> getAge = People::getAge;
第二个参数 keyComparator就很好理解了,表示使用的比较规则。
对 c1,c2 按照 第一个参数 keyExtractor 提供的规则进行提取特征,然后第二个参数keyComparator对这两个特征进行比较。下面的式子其实可以概括为 3.1 的 (x1,x2)-> int
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2))
Comparator & Serializable 为 Java 8 新特性:同时满足这两个类型约束
理解了这个方法后,其它该系列的方法就好理解了,这里不再赘述。目前 comparing 系列方法使用更加广泛。我们举一些例子:
List<People> peoples = new ArrayList<>();
// ………………
// 按照年龄从低到高排序
peoples.sort

本文围绕Java的Comparator接口展开,介绍其作为函数式接口用于集合排序的功能。详细讲解了Comparator中的compare、comparing等方法,分析了相关源码,解释了泛型通配符的使用及作用。还探讨了排序时compare返回值与升降序的关系,以及底层归并排序和快速排序对compare方法的调用。
最低0.47元/天 解锁文章
3538

被折叠的 条评论
为什么被折叠?



