Сортировка элементов В чем разница между Comparable и Comparator?

Java задняя часть опрос
Сортировка элементов В чем разница между Comparable и Comparator?

Эта статья была включена в мой сборник статей:git ee.com/oppo/inter V…

В языке Java Comparable и Comparator используются для сортировки элементов, но между ними есть существенные различия. Оба они также являются общими вопросами интервью, поэтому сегодня мы обсудим их вместе.

1. Буквально разные значения

Давайте сначала разберемся с буквальным значением двух слов: Comparable переводится на китайский язык и означает «сравнение», а Comparator означает «сравнение». Comparable оканчивается на -able, указывая на то, что он обладает определенной способностью, а Comparator оканчивается на -or, указывая на то, что он является участником сравнения Это необходимо для понимания разницы между ними из буквального значения.

2. Разные

Оба являются интерфейсами верхнего уровня, но методы и способы их использования разные, рассмотрим их отдельно.

2.1 Comparable

Интерфейс Comparable имеет только один метод, compareTo. Реализация интерфейса Comparable и переопределение метода compareTo могут реализовать сортировку класса. Он поддерживает сортировку Collections.sort и Arrays.sort. ​

Когда мы не используем Comparable, выполнение программы выглядит так:

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.ArrayList;
import java.util.List;

public class ComparableExample {
    public static void main(String[] args) {
        // 创建对象
        Person p1 = new Person(1, 18, "Java");
        Person p2 = new Person(2, 22, "MySQL");
        Person p3 = new Person(3, 6, "Redis");
        // 添加到集合
        List<Person> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        // 打印集合信息
        list.forEach(p -> System.out.println(p.getName() +
                ":" + p.getAge()));
    }
}

// 以下 set/get/toString 都使用的是 lombok 提供的注解
@Getter 
@Setter
@ToString
class Person {
    private int id;
    private int age;
    private String name;

    public Person(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
}

Результат выполнения программы следующий:image.pngКак видно из приведенного выше рисунка, когда пользовательский класс Person не реализует Comparable, коллекция List не сортируется, и в качестве порядка вывода может использоваться только порядок вставки элементов. ​

Однако в это время у начальника есть требование: нужно реверсировать по возрастному признаку объекта Person, то есть по возрастному признаку от большого к маленькому, в это время можно попросить об этом. Главный герой нашей статьи: Comparable появляется. ​

Comparable заключается в реализации интерфейса Compailable в классе настраиваемых объектов и переписывании метода CompareTo для реализации настраиваемых правил сортировки. Конкретный код реализации выглядит следующим образом:

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ComparableExample {
    public static void main(String[] args) {
        // 创建对象
        Person p1 = new Person(1, 18, "Java");
        Person p2 = new Person(2, 22, "MySQL");
        Person p3 = new Person(3, 6, "Redis");
        // 添加对象到集合
        List<Person> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        // 进行排序操作(根据 Person 类中 compareTo 中定义的排序规则)
        Collections.sort(list);
        // 输出集合中的顺序
        list.forEach(p -> System.out.println(p.getName() +
                ":" + p.getAge()));
    }
}
//  以下 set/get/toString 都使用的是 lombok 提供的注解实现的
@Getter
@Setter
@ToString
static class Person implements Comparable<Person> {
    private int id;
    private int age;
    private String name;

    public Person(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    @Override
    public int compareTo(Person p) {
        return p.getAge() - this.getAge();
    }
}

Результат выполнения программы показан на следующем рисунке:image.png

сравнение с описанием метода сортировки

Параметр p, полученный методом compareTo, представляет собой сравниваемый объект.Сортировка заключается в сравнении текущего объекта с сравниваемым объектом, а затем возврате значения типа int. Правило сортировки от меньшего к большему в положительном порядке: использовать значение текущего объекта минус значение сравниваемого объекта, а правило сортировки в обратном порядке от большего к меньшему прямо противоположное: значение объекта сравнения минус стоимость текущего объекта. ​

Примечание. Если пользовательский объект не реализует интерфейс Comparable, его нельзя отсортировать с помощью метода Collections.sort, и компилятор выдаст следующую ошибку:image.png

2.2 Comparator

Методы сортировки Comparator и Comparable различаются. Метод сортировки Comparable — compareTo, а метод сортировки Comparator — сравнение. Конкретный код реализации выглядит следующим образом:

import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ComparatorExample {
    public static void main(String[] args) {
        // 创建对象
        Person p1 = new Person(1, 18, "Java");
        Person p2 = new Person(2, 22, "MySQL");
        Person p3 = new Person(3, 6, "Redis");
        // 添加对象到集合
        List<Person> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        // 进行排序操作(根据 PersonComparator 中定义的排序规则)
        Collections.sort(list, new PersonComparator());
        // 输出集合中的顺序
        list.forEach(p -> System.out.println(p.getName() +
                ":" + p.getAge()));
    }
}
/**
  * 用于 Person 类的比较器
  */
class PersonComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p2.getAge() - p1.getAge();
    }
}
@Getter
@Setter
class Person {
    private int id;
    private int age;
    private String name;

    public Person(int id, int age, String name) {
        this.id = id;
        this.age = age;
    }
}

Результат выполнения программы показан на следующем рисунке:image.png

Расширение: анонимный класс компаратора

Помимо создания пользовательских компараторов, Comparator также может использовать анонимные классы для более быстрого и удобного выполнения функций пользовательских компараторов.Конкретная реализация кода выглядит следующим образом:

import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class ComparatorExample {
    public static void main(String[] args) {
        // 构建并添加数据
        List<Person> list = new ArrayList<>();
        list.add(new Person(1, 18, "Java"));
        list.add(new Person(2, 20, "MySQL"));
        list.add(new Person(3, 6, "Redis"));
        // 使用 Comparator 匿名类的方式进行排序
        list.sort(new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                return p2.getAge() - p1.getAge();
            }
        });
        // 打印集合数据
        list.forEach(p -> System.out.println(p.getName() +
                ":" + p.getAge()));
    }
}

@Getter
@Setter
static class Person {
    private int id;
    private int age;
    private String name;

    public Person(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
}

Результат выполнения программы показан на следующем рисунке:image.png

3. Используются разные сценарии

Из кода реализации приведенного выше примера видно, что использование Comparable должно изменить исходный класс, то есть, если вы хотите отсортировать класс, вы должны реализовать интерфейс Comparable и переписать метод compareTo в этом классе, поэтому Comparable больше похож на интерфейс «Да» для сортировки внутри». ​

Использование Comparator отличается, Comparator не нужно изменять исходный класс. То есть в самом крайнем случае, даже если класс Person предоставляется третьей стороной, мы все равно можем реализовать функцию сортировки стороннего класса Person, создав новый пользовательский компаратор Comparator. Другими словами, интерфейс Comparator может реализовать отделение от исходного класса и реализовать функцию сортировки без изменения исходного класса, поэтому Comparator можно рассматривать как интерфейс, обеспечивающий сортировку «извне».

Суммировать

Comparable и Comparator оба используются для реализации сортировки элементов. Различия между ними заключаются в следующем:

  • Comparable означает «сравнение», а Comparator означает «компаратор»;
  • Comparable реализует сортировку, переопределяя метод compareTo, а Comparator реализует сортировку, переопределяя метод сравнения;
  • Comparable должен реализовать метод сортировки внутри пользовательского класса, тогда как Comparator определяется извне и реализует сортировку.

Итак, суммируйте разницу между ними в одном предложении: Comparable можно рассматривать как интерфейс для «внутренней» сортировки, а Comparator — это интерфейс для «внешней» сортировки.

Самостоятельно судить о правильном и неправильном, слушать других и подсчитывать выгоды и потери.

Введение блогера: Программисты, родившиеся в 1980-х годах, «упорствовали» в ведении блога в течение 12 лет.Хобби: чтение, бег трусцой, бадминтон.

Мой официальный аккаунт: Анализ вопросов Java-интервью