Java использует Comparator для реализации групповой сортировки

Java

В базе данных мы можем использоватьorder byа такжеgroup byЛегко реализовать функции группировки и сортировки, так как же реализовать это на Java? Давайте учиться вместе

Comparatorа такжеComparable

  • ComparableИнтерфейс сортировки, класс, реализующий этот интерфейс, указывающий, что класс поддерживает функцию сортировки, переписатьcompareToметоды позволяют программе сортировать массив или список по нашему желанию

  • Comparatorэто интерфейс компаратора, если нам нужно отсортировать класс, а класс не реализуетComparableинтерфейс, то мы можем реализоватьComparatorинтерфейс для поддержания возможности сортировки класса

простая сортировка

  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Передний

    // 按分数进行降序排序
    Comparator<Student> comparator = (o1, o2) -> o2.getScore().compareTo(o1.getScore());
    
  4. Результаты тестовой сортировки

    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:

Ссылка на исходный код для этого примера

Из-за моего ограниченного уровня есть неправильные места, надеюсь меня поправят, спасибо