假設我們有以下三個列表(一個數(shù)字列表,一個字符串列表,和一個 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; ...}
接下來,我們想要在流管道中對這些列表進行排序。
通過自然順序排序 通過自然順序排序非常簡單。我們所要做得就是調(diào)用內(nèi)置得中間操作 sorted():
nrs.stream() .sorted() .forEach(System.out::println);strs.stream() .sorted() .forEach(System.out::println);
如果 nrs 包含 1, 6, 3, 8, 2, 3, 和 0,那嗎 sorted() 將產(chǎn)生 0, 1, 2, 3, 3, 6, 和 8。因此,對于數(shù)字,自然順序是按值升序。如果 strs 包含 "book", "old", "new", "quiz", "around", 和 "tick",那嗎 sorted() 將產(chǎn)生 "around", "book", "new", "old", "quiz", 和 "tick"。因此,對于字符串,自然順序是按字母順序。
如果我們顯式地通過 sorted(Comparator<? super T> comparator) 調(diào)用 Integer#compareTo() 和 String#compareTo(),也專業(yè)獲的相同得結(jié)果:
nrs.stream() .sorted((n1, n2) -> n1感謝原創(chuàng)分享者pareTo(n2)) .forEach(System.out::println);strs.stream() .sorted((s1, s2) -> s1感謝原創(chuàng)分享者pareTo(s2)) .forEach(System.out::println);
或者,我們專業(yè)使用 java.util.Comparator 功能接口,如下所示:
nrs.stream() .sorted(Comparator.naturalOrder()) .forEach(System.out::println);strs.stream() .sorted(Comparator.naturalOrder()) .forEach(System.out::println);
這三種方法都返回相同得結(jié)果。
反轉(zhuǎn)自然順序 通過 Comparator.reverseOrder() 專業(yè)反轉(zhuǎn)自然順序,如下所示:
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() 將產(chǎn)生 8, 6, 3, 3, 2, 1, 和 0。反轉(zhuǎn)數(shù)字得自然順序會的到按值降序。如果 strs 包含 "book", "old", "new", "quiz", "around", 和 "tick",那嗎 sorted() 將產(chǎn)生 "tick", "quiz", "old", "new", "book", 和 "around"。因此,對于字符串,反轉(zhuǎn)自然順序會的到按字母順序反轉(zhuǎn)。
排序和空值 如果 nrs/strs 也包含空值,那嗎所有前面得示例都會拋出 NullPointerException。但是,java.util.Comparator 公開了兩種方法,最優(yōu)我們首先(nullsFirst(Comparator<? super T> comparator))或最后(nullsLast(Comparator<? super T> comparator))對空值進行排序。它們專業(yè)在以下示例中使用:
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);
第三個示例首先對空值進行排序,然后按降序排序數(shù)字。
敬請關(guān)注寫自定義比較器 有時我們需要自定義比較器。例如,如果我們想要按最后一個字符升序?qū)?strs 進行排序,那嗎我們專業(yè)敬請關(guān)注寫一個自定義比較器,如下所示:
strs.stream() .sorted((s1, s2) -> Character感謝原創(chuàng)分享者pare(s1.charAt(s1.length() - 1), s2.charAt(s2.length() - 1))) .forEach(System.out::println);
如果 strs 包含 "book", "old", "new", "quiz", "around", 和 "tick",那嗎 sorted() 將產(chǎn)生 "old", "around", "book", "tick", "new", 和 "quiz"。
但是,自定義比較器通常用于對我們得模型進行排序。例如,如果我們需要對 cars 列表進行排序,那嗎我們需要定義一個比較器。我們不能只是說:
cars.stream() .sorted() .forEach(System.out::println);
這將無法敬請關(guān)注譯,因為 Car 對象沒有比較器。一種方法是實現(xiàn) Comparable 接口并重寫 compareTo(Car c) 方法。例如,如果我們想按馬力升序?qū)ζ囘M行排序,那嗎我們首先按照以下方式實現(xiàn) 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; }}
現(xiàn)在,我們專業(yè)成功地敬請關(guān)注寫這個:
cars.stream() .sorted() .forEach(System.out::println);
或者,如果我們不能更改 Car 代碼,我們專業(yè)嘗試使用現(xiàn)有得 Comparator 方法之一,該方法最優(yōu)我們推送一個包含排序鍵得函數(shù),并返回一個自動按該鍵進行比較得比較器。由于馬力是一個整數(shù),我們專業(yè)使用 comparingInt(ToIntFunction<? super T> keyExtractor),如下所示:
cars.stream() .sorted(Comparator感謝原創(chuàng)分享者paringInt(Car::getHorsepower)) .forEach(System.out::println);
或者,以相反得順序:
cars.stream() .sorted(Comparator感謝原創(chuàng)分享者paringInt( Car::getHorsepower).reversed()) .forEach(System.out::println);
您專家還對 comparingLong(ToLongFunction) 和 comparingDouble(ToDoubleFunction) 感興趣。ToIntFunction、ToLongFunction 和 ToDoubleFunction 是 Function 得特化。在這種情況下,我們專業(yè)說什嗎 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感謝原創(chuàng)分享者paring(Car::getFuel, Comparator.nullsLast(Comparator.naturalOrder()))) .forEach(System.out::println);
這是另一個示例,用于按燃料類型最后一個字符升序?qū)ζ囘M行排序,空值放在最后:
cars.stream() .sorted(Comparator感謝原創(chuàng)分享者paring(Car::getFuel, Comparator.nullsLast((s1, s2) -> Character感謝原創(chuàng)分享者pare(s1.charAt(s1.length() - 1), s2.charAt(s2.length() - 1))))) .forEach(System.out::println);
完成!在下一個問題中,我們將對一個映射進行排序。