Java利用Comparator實現分組排序

在數據庫中咱們可使用 order bygroup by 輕鬆實現分組和排序的功能,那麼在Java中咱們又該如何實現呢?下面咱們一塊兒來研究一番java

ComparatorComparable

  • Comparable 是一個排序接口,實現了該接口的類,表示該類支持排序功能,重寫 compareTo 方法可以使程序按照咱們的意願對數組或列表進行排序git

  • Comparator 是一個比較器接口,若是咱們須要對類進行排序,而該類並無實現 Comparable 接口,那麼咱們能夠經過實現 Comparator 接口來保持類的排序能力github

簡單排序

  1. 建立一個 Bean 類,咱們將對該類進行排序數據庫

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student {
    
       /** * 班級名稱 */
       private String className;
    
       /** * 學生姓名 */
       private String name;
    
       /** * 分數 */
       private Integer score;
    }
    複製代碼
  2. 準備一些數據,用於測試數組

    final String classOne = "一班";
    final String classTwo = "二班";
    final String classThree = "三班";
    List<Student> students = new ArrayList<>();
    students.add(new Student(classOne, "李一", 43));
    students.add(new Student(classOne, "王二", 75));
    students.add(new Student(classOne, "張三", 91));
    students.add(new Student(classTwo, "郭子", 59));
    students.add(new Student(classTwo, "潘子", 88));
    students.add(new Student(classTwo, "劉子", 97));
    students.add(new Student(classThree, "陳六", 66));
    students.add(new Student(classThree, "唐七", 77));
    students.add(new Student(classThree, "周八", 89));
    複製代碼
  3. 建立一個 Comparator 對象測試

    若是咱們將第一參數與第二個參數進行比較,那麼表示這是一個升序序列(天然排序),不然表示一個降序序列。 固然這樣說並不徹底準確,主要仍是看返回的整數值是大於零、小於零仍是等於零,只有當大於零時對象 o2 纔會置於對象 o1 前面spa

    // 按分數進行降序排序
    Comparator<Student> comparator = (o1, o2) -> o2.getScore().compareTo(o1.getScore());
    複製代碼
  4. 測試排序結果code

    Collections.sort(students, comparator);
    students.forEach(System.out::println);
    複製代碼

    打印結果,能夠看出列表是按分數進行排序的,接下來咱們將對班級名稱進行分組並按分數排序對象

    Student(className=二班, name=劉子, score=97)
    Student(className=一班, name=張三, score=91)
    Student(className=三班, name=周八, score=89)
    Student(className=二班, name=潘子, score=88)
    Student(className=三班, name=唐七, score=77)
    Student(className=一班, name=王二, score=75)
    Student(className=三班, name=陳六, score=66)
    Student(className=二班, name=郭子, score=59)
    Student(className=一班, name=李一, score=43)
    複製代碼

分組排序

  1. 建立一個分組排序的 Comparator 對象排序

    因爲咱們須要按班級名稱進行分組排序,因此咱們必須進行兩次計較,第一次比較是不是相同的班級名稱,若是不是直接返回比較的結果值便可,不然返回分數的比較結果

    Comparator<Student> groupComparator = (o1, o2) -> {
        int diff = o1.getClassName().compareTo(o2.getClassName());
        return diff == 0 ? o2.getScore().compareTo(o1.getScore()) : diff;
    };
    複製代碼
  2. 測試排序結果

    Collections.sort(students, groupComparator);
    students.forEach(System.out::println);
    複製代碼

    打印結果,能夠看出確實時按班級分組排序的,可是若是咱們想要班級名稱也是按順序排的呢,怎麼作?

    Student(className=一班, name=張三, score=91)
    Student(className=一班, name=王二, score=75)
    Student(className=一班, name=李一, score=43)
    Student(className=三班, name=周八, score=89)
    Student(className=三班, name=唐七, score=77)
    Student(className=三班, name=陳六, score=66)
    Student(className=二班, name=劉子, score=97)
    Student(className=二班, name=潘子, score=88)
    Student(className=二班, name=郭子, score=59)
    複製代碼

有序的分組排序

如何讓分組的名稱按照咱們想要的順序出現?簡單,請看下面

  1. 定義一個分組順序

    分組順序用來判斷該分組所在位置,這樣咱們就能夠自定義分組的位置,從而實現有序的分組

    Map<String, Integer> groupOrder = new HashMap<>(4);
    groupOrder.put(classOne, 1);
    groupOrder.put(classTwo, 2);
    groupOrder.put(classThree, 3);
    複製代碼
  2. 建立一個有序的分組排序 Comparator 對象

    經過自定義的班級順序來決定班級名稱出現的位置

    Comparator<Student> orderlyGroupComparator = (o1, o2) -> {
        int diff = groupOrder.get(o1.getClassName()).compareTo(groupOrder.get(o2.getClassName()));
        return diff == 0 ? o2.getScore().compareTo(o1.getScore()) : diff;
    };
    複製代碼
  3. 測試排序結果

    Collections.sort(students, orderlyGroupComparator);
    students.forEach(System.out::println);
    複製代碼

    打印結果

    Student(className=一班, name=張三, score=91)
    Student(className=一班, name=王二, score=75)
    Student(className=一班, name=李一, score=43)
    Student(className=二班, name=劉子, score=97)
    Student(className=二班, name=潘子, score=88)
    Student(className=二班, name=郭子, score=59)
    Student(className=三班, name=周八, score=89)
    Student(className=三班, name=唐七, score=77)
    Student(className=三班, name=陳六, score=66)
    複製代碼

總結

如今回過去看,原來分組排序如此的簡單呀,不過這徹底得益於 Comparator 的強大,你也徹底能夠選擇實現 Comparable 接口來達到相同的效果。

當有新的挑戰時,咱們必定要多思考:facepunch:

本示例源代碼參考

因爲本人水平有限,有不正確的地方,還望指正,謝謝

相關文章
相關標籤/搜索