Vis*_*dar 5 java collections lambda comparator
据我了解 Comparator 是一个函数接口,用于比较 2 个对象,int compare(T o1, T o2)作为带有两个参数的抽象函数。但还有一种函数Comparator.comparing(s->s)可以采用只有一个输入参数的 lambda 函数。例如使用流对集合进行排序
List<String> projects=Arrays.asList("abc","def","sss","aaa","bbb");
projects.stream().sorted((x,y)->y.compareTo(x)).forEach(s->System.out.println(s));
projects.stream().sorted(Comparator.comparing(s->s)).forEach(s->System.out.println(s));
Run Code Online (Sandbox Code Playgroud)
Sorted 方法采用 Comparator 作为参数。所以我能够理解第一个 lambda 表达式,但我想知道Comparator.comparing(s->s)ie 的使用是Comparator.comparing()用于将单参数 lambda 表达式转换为双参数表达式,还是还有其他用途。另请解释以下函数声明的部分。
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
Run Code Online (Sandbox Code Playgroud)
用于
Comparator.comparing()将单参数 lambda 表达式转换为双参数?
是的,你可以这样想。
在对事物进行排序时,您应该指定“给定两个事物a和b,其中哪个更大,或者它们相等?” 用一个Comparator<T>。anda就是b为什么它有 2 个 lambda 参数,并且您返回一个整数来指示您对该问题的答案。
然而,更方便的方法是指定“给定一个事物,您想要按其哪x一部分进行排序?”。这就是你可以用 的论证来做的事情。xkeyExtractorComparator.comparing
比较:
/*
given two people, a and b, the comparison result between a and b is the
comparison result between a's name and b's name
*/
Comparator<Person> personNameComparator =
(a, b) -> a.getName().compareTo(b.getName());
/*
given a person x, compare their name
*/
Comparator<Person> personNameComparator =
Comparator.comparing(x -> x.getName()); // or Person::getName
Run Code Online (Sandbox Code Playgroud)
后者显然更加简洁和直观。我们倾向于考虑按什么事物排序,而不是如何准确地比较两个事物,以及根据比较结果返回确切的数字。
至于声明comparing:
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
Run Code Online (Sandbox Code Playgroud)
该<T, U extends Comparable<? super U>>部分首先声明两个泛型类型参数 -T是比较器比较的内容(Person在上面的情况下),并且U是您实际比较的类型(String在上面的情况下),因此它extends Comparable。
keyExtractor是您传入的参数,例如,它应该回答“当给定 a 时,您想要比较的a 是什么?”x -> x.getName()的问题。TU
? super如果您对和感到困惑? extends,请阅读什么是 PECS?。
如果您还没有意识到,其实现comparing基本上可以归结为:
return (a, b) -> keyExtractor.apply(a).compareTo(keyExtractor.apply(b));
Run Code Online (Sandbox Code Playgroud)
Comparator#compare(T o1, T o2)比较两个对象并根据以下条件返回一个整数值:
Comparator.comparing(Function<? super T, ? extends U> key)返回一个Comparator<T>按该排序键进行比较的值。
主要区别在于该compare方法提供单点比较,而comparing链接到其他函数以提供多个比较点。
假设你有一堂课Person
public class Person implements Comparable<Person> {
private String firstName;
private String lastName;
private int age;
// rest of class omitted
}
Run Code Online (Sandbox Code Playgroud)
如果您比较两个Person实例p1与p2using compare(p1, p2),则将执行比较,并且将根据类规定的某些自然顺序对两个对象进行排序。相反,如果您想使用 比较相同的两个实例comparing(),则将根据您选择基于类的某些属性进行比较的任何标准来执行比较。例如:Comparator.comparing(Person::getFirstName)。
正如我之前所说,因为comparing返回的是一个Comparator而不是一个值,所以您可以链接多个比较。例如:Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstName);
至于返回类型的含义,可以在这里<T, U extends Comparable<? super U>> Comparator<T>找到解释。
我想补充一点,班级必须具有可比性才能compare(T o1, T o2)发挥作用。字符串对象具有可比性,因为它们实现了此接口。也就是说,如果一个类不是Comparable,您仍然可以使用comparing方法,因为正如我所说,您可以选择要使用该类的哪个属性进行比较,并且这些属性可能是可比较的(即在这种情况下为 String上例中的人名或年龄)。
| 归档时间: |
|
| 查看次数: |
21935 次 |
| 最近记录: |