假设我们有以下三个列表(一个数字列表,一个字符串列表,和一个 Car 列表):
List<Integer> nrs = new ArrayList<>();List<String> strs = new ArrayList<>();List<Car> cars = List.of(...);public class Car { private final String brand; private final String fuel; private final int horsepower; ...}
接下来,我们想要在流管道中对这些列表进行排序。
通过自然顺序排序 通过自然顺序排序非常简单。我们所要做得就是调用内置得中间操作 sorted():
nrs.stream() .sorted() .forEach(System.out::println);strs.stream() .sorted() .forEach(System.out::println);
如果 nrs 包含 1, 6, 3, 8, 2, 3, 和 0,那吗 sorted() 将产生 0, 1, 2, 3, 3, 6, 和 8。因此,对于数字,自然顺序是按值升序。如果 strs 包含 "book", "old", "new", "quiz", "around", 和 "tick",那吗 sorted() 将产生 "around", "book", "new", "old", "quiz", 和 "tick"。因此,对于字符串,自然顺序是按字母顺序。
如果我们显式地通过 sorted(Comparator<? super T> comparator) 调用 Integer#compareTo() 和 String#compareTo(),也专业获的相同得结果:
nrs.stream() .sorted((n1, n2) -> n1感谢原创分享者pareTo(n2)) .forEach(System.out::println);strs.stream() .sorted((s1, s2) -> s1感谢原创分享者pareTo(s2)) .forEach(System.out::println);
或者,我们专业使用 java.util.Comparator 功能接口,如下所示:
nrs.stream() .sorted(Comparator.naturalOrder()) .forEach(System.out::println);strs.stream() .sorted(Comparator.naturalOrder()) .forEach(System.out::println);
这三种方法都返回相同得结果。
反转自然顺序 通过 Comparator.reverseOrder() 专业反转自然顺序,如下所示:
nrs.stream() .sorted(Comparator.reverseOrder()) .forEach(System.out::println);strs.stream() .sorted(Comparator.reverseOrder()) .forEach(System.out::println);
如果 nrs 包含 1, 6, 3, 8, 2, 3, 和 0,那吗 sorted() 将产生 8, 6, 3, 3, 2, 1, 和 0。反转数字得自然顺序会的到按值降序。如果 strs 包含 "book", "old", "new", "quiz", "around", 和 "tick",那吗 sorted() 将产生 "tick", "quiz", "old", "new", "book", 和 "around"。因此,对于字符串,反转自然顺序会的到按字母顺序反转。
排序和空值 如果 nrs/strs 也包含空值,那吗所有前面得示例都会抛出 NullPointerException。但是,java.util.Comparator 公开了两种方法,最优我们首先(nullsFirst(Comparator<? super T> comparator))或最后(nullsLast(Comparator<? super T> comparator))对空值进行排序。它们专业在以下示例中使用:
nrs.stream() .sorted(Comparator.nullsFirst(Comparator.naturalOrder())) .forEach(System.out::println); nrs.stream() .sorted(Comparator.nullsLast(Comparator.naturalOrder())) .forEach(System.out::println);nrs.stream() .sorted(Comparator.nullsFirst(Comparator.reverseOrder())) .forEach(System.out::println);
第三个示例首先对空值进行排序,然后按降序排序数字。
敬请关注写自定义比较器 有时我们需要自定义比较器。例如,如果我们想要按最后一个字符升序对 strs 进行排序,那吗我们专业敬请关注写一个自定义比较器,如下所示:
strs.stream() .sorted((s1, s2) -> Character感谢原创分享者pare(s1.charAt(s1.length() - 1), s2.charAt(s2.length() - 1))) .forEach(System.out::println);
如果 strs 包含 "book", "old", "new", "quiz", "around", 和 "tick",那吗 sorted() 将产生 "old", "around", "book", "tick", "new", 和 "quiz"。
但是,自定义比较器通常用于对我们得模型进行排序。例如,如果我们需要对 cars 列表进行排序,那吗我们需要定义一个比较器。我们不能只是说:
cars.stream() .sorted() .forEach(System.out::println);
这将无法敬请关注译,因为 Car 对象没有比较器。一种方法是实现 Comparable 接口并重写 compareTo(Car c) 方法。例如,如果我们想按马力升序对汽车进行排序,那吗我们首先按照以下方式实现 Comparable:
public class Car implements Comparable<Car> { ... 等Override public int compareTo(Car c) { return this.getHorsepower() > c.getHorsepower() ? 1 : this.getHorsepower() < c.getHorsepower() ? -1 : 0; }}
现在,我们专业成功地敬请关注写这个:
cars.stream() .sorted() .forEach(System.out::println);
或者,如果我们不能更改 Car 代码,我们专业尝试使用现有得 Comparator 方法之一,该方法最优我们推送一个包含排序键得函数,并返回一个自动按该键进行比较得比较器。由于马力是一个整数,我们专业使用 comparingInt(ToIntFunction<? super T> keyExtractor),如下所示:
cars.stream() .sorted(Comparator感谢原创分享者paringInt(Car::getHorsepower)) .forEach(System.out::println);
或者,以相反得顺序:
cars.stream() .sorted(Comparator感谢原创分享者paringInt( Car::getHorsepower).reversed()) .forEach(System.out::println);
您专家还对 comparingLong(ToLongFunction) 和 comparingDouble(ToDoubleFunction) 感兴趣。ToIntFunction、ToLongFunction 和 ToDoubleFunction 是 Function 得特化。在这种情况下,我们专业说什吗 comparingInt()、comparingLong() 和 comparingDouble() 是 comparing() 得特化,它有两种口味:comparing(Function<? super T,? extends U> keyExtractor) 和 comparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)。以下是使用第二种口味得 comparing() 对汽车按燃料类型(自然顺序)升序排序得示例,空值放在最后:
cars.stream() .sorted(Comparator感谢原创分享者paring(Car::getFuel, Comparator.nullsLast(Comparator.naturalOrder()))) .forEach(System.out::println);
这是另一个示例,用于按燃料类型最后一个字符升序对汽车进行排序,空值放在最后:
cars.stream() .sorted(Comparator感谢原创分享者paring(Car::getFuel, Comparator.nullsLast((s1, s2) -> Character感谢原创分享者pare(s1.charAt(s1.length() - 1), s2.charAt(s2.length() - 1))))) .forEach(System.out::println);
完成!在下一个问题中,我们将对一个映射进行排序。