Comparator.comparing(…)
方法旨在创建一个 Comparator
,该比较器使用基于对象属性的顺序进行比较。当将 lambda 表达式 i -> i
(这是 (int i) -> { return i; }
的简写)作为属性提供者函数时,生成的 Comparator
将直接比较值本身。如果要比较的对象具有像 Integer
一样的自然排序,则此方法有效。
因此,
Stream.of(1,2,4,3,5).max(Comparator.comparing(i -> i))
.ifPresent(maxInt->System.out.println("Maximum number in the set is " + maxInt));
与...相同
Stream.of(1,2,4,3,5).max(Comparator.naturalOrder())
.ifPresent(maxInt->System.out.println("Maximum number in the set is " + maxInt));
虽然后者更有效率,因为它被实现为所有具有自然排序(并实现 Comparable
)类型的单例。
为什么 max
需要一个 Comparator
呢?这是因为你正在使用通用类 Stream
,其中可能包含任意对象。
这允许例如像这样使用:streamOfPoints.max(Comparator.comparing(p->p.x))
找到 x
值最大的点,而 Point
本身没有自然排序。或者像这样做:streamOfPersons.sorted(Comparator.comparing(Person::getAge))
。
当使用专门的 IntStream
时,可以直接使用自然顺序,这可能更有效率:
IntStream.of(1,2,4,3,5).max()
.ifPresent(maxInt->System.out.println("Maximum number in the set is " + maxInt));
为了说明“自然顺序”和基于属性的顺序之间的差异:
Stream.of("a","bb","aaa","z","b").max(Comparator.naturalOrder())
.ifPresent(max->System.out.println("Maximum string in the set is " + max));
这将打印
集合中的最大字符串为z
因为String的自然排序是按字典顺序排列,其中z大于b,b大于a。
另一方面,
Stream.of("a","bb","aaa","z","b").max(Comparator.comparing(s->s.length()))
.ifPresent(max->System.out.println("Maximum string in the set is " + max));
将会打印
集合中最长的字符串是aaa
因为aaa
是流中所有String
中长度最长的。这是使用Comparator.comparing
的预期用例,当使用方法引用时可以使其更易读,即Comparator.comparing(String::length)
,几乎可以自我解释......
Comparator.naturalOrder()
相同。因此对于IntStream
,您甚至可以省略Comparator
并实现相同的效果。 - Holger