Когда использовать Comparable и Comparator - PullRequest
103 голосов
/ 15 февраля 2010

У меня есть список объектов, которые мне нужно отсортировать по полю, скажем, Score. Не задумываясь, я написал новый класс, который реализует Comparator, который выполняет задачу, и она работает.

Теперь, оглядываясь назад на это, я задаюсь вопросом, должен ли я вместо этого иметь мой класс, реализующий Comparable, вместо того, чтобы создавать новый класс, который реализует Comparator. Счет - это единственное поле, в котором объекты будут упорядочены.

  1. Что я сделал приемлемым в качестве практики?

  2. Правильный ли подход: «Сначала нужно, чтобы класс реализовал Comparable (для естественного упорядочения), и если требуется альтернативное сравнение полей, то создайте новый класс, который реализует Comparator»?

  3. Если (2) выше верно, то означает ли это, что следует реализовывать Comparator только после того, как класс реализует Comparable? (Предполагая, что мне принадлежит оригинальный класс).

Ответы [ 19 ]

122 голосов
/ 15 февраля 2010

Используйте Comparable, если вы хотите определить стандартное (естественное) упорядочение поведения рассматриваемого объекта, обычной практикой является использование технической или естественной (базы данных? ) идентификатор объекта для этого.

Используйте Comparator, если вы хотите определить внешний управляемый порядок упорядочения, это может переопределить стандартное поведение упорядочения.

76 голосов
/ 15 февраля 2010

Я бы сказал, что объект должен реализовывать Comparable, если это очевидный естественный способ сортировки класса, и любой, кому потребуется сортировка класса, обычно хотел бы сделать это таким образом.

Если, однако, сортировка была необычным использованием класса, или сортировка имеет смысл только для конкретного случая использования, тогда Comparator является лучшим вариантом.

Другими словами, учитывая имя класса, понятно, как будет сортироваться сопоставимый код, или вам приходится прибегать к чтению javadoc? Если это последнее, то шансы на то, что каждый будущий случай использования сортировки потребует компаратора, в этом случае реализация сопоставимого может замедлить пользователей класса, а не ускорить их.

53 голосов
/ 15 февраля 2010

Использование Comparable:

  • если объект находится под вашим контролем.
  • если сравнивающее поведение является основным сравнивающим поведением.

Использование Comparator:

  • если объект находится вне вашего контроля и вы не можете заставить его реализовать Comparable.
  • когда вы хотите сравнить поведение, отличное от поведения по умолчанию (которое задается Comparable).
20 голосов
/ 06 июля 2015

Сравнимо - java.lang.Comparable: int compareTo(Object o1)

Сравнимый объект способен сравнивать себя с другим объектом. Сам класс должен реализовывать интерфейс java.lang.Comparable, чтобы иметь возможность сравнивать его экземпляры.

  • Возможность сравнения текущего объекта с предоставленным объектом.
  • Используя это, мы можем реализовать only one sort sequence на основе свойств экземпляров. Пример: Person.id
  • В некоторых предопределенных классах, таких как String, Wrapper, Date, Calendar, реализован интерфейс Comparable.

Компаратор - java.util.Comparator: int compare(Object o1, Object o2)

Объект сравнения способен сравнивать два разных объекта. Класс сравнивает не свои экземпляры, а экземпляры некоторых других классов. Этот класс компаратора должен реализовывать интерфейс java.util.Comparator.

  • Возможность сравнения любых двух объектов одного типа.
  • Используя это, мы можем реализовать many sort sequence и присвоить каждому имя, основываясь на свойствах экземпляров. Пример: Person.id, Person.name, Person.age
  • Мы можем реализовать интерфейс Comparator для наших предопределенных классов для настраиваемой сортировки.

* * Пример тысячу сорок четыре: * * 1045
public class Employee implements Comparable<Employee> {

    private int id;
    private String name;
    private int age;
    private long salary;

    // Many sort sequences can be created with different names.
    public static Comparator<Employee> NameComparator = new Comparator<Employee>() {         
        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getName().compareTo(e2.getName());
        }
    };
    public static Comparator<Employee> idComparator = new Comparator<Employee>() {       
        @Override
        public int compare(Employee e1, Employee e2) {
            return Integer.valueOf(e1.getId()).compareTo(Integer.valueOf(e2.getId()));
        }
    };

    public Employee() { }
    public Employee(int id, String name, int age, long salary){
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }
    // setters and getters.

    // Only one sort sequence can be created with in the class.
    @Override
    public int compareTo(Employee e) {
    //return Integer.valueOf(this.id).compareTo(Integer.valueOf(e.id));
    //return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0)));
        if (this.id > e.id) {
            return 1;
        }else if(this.id < e.id){
            return -1;
        }else {
            return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0)));
        }

    }   

    public static void main(String[] args) {

        Employee e1 = new Employee(5, "Yash", 22, 1000);
        Employee e2 = new Employee(8, "Tharun", 24, 25000);

        List<Employee> list = new ArrayList<Employee>();
        list.add(e1);
        list.add(e2);
        Collections.sort(list); // call @compareTo(o1)
        Collections.sort(list, Employee.nameComparator); // call @compare (o1,o2)
        Collections.sort(list, Employee.idComparator); // call @compare (o1,o2)
    }
}
  • Для настраиваемой сортировки мы используем компаратор @compare (o1, o2), для других сценариев - сопоставимый @compareTo (o1) без изменения кода, если мы хотим отсортировать более одного поля, тогда мы используем компаратор.

Для Java 8 Lambda: Comparator см. Мой пост.

9 голосов
/ 06 июля 2011

Comparable следует использовать при сравнении экземпляров одного и того же класса.

Компаратор можно использовать для сравнения экземпляров разных классов.

Comparable реализуется классом, который должен определить естественный порядок для своих объектов. Like String реализует Comparable.

Если вам нужен другой порядок сортировки, он может реализовать компаратор и определить собственный способ сравнения двух экземпляров.

9 голосов
/ 16 ноября 2014

Comparator делает все то же, что и сравнимый, плюс еще.

| | Comparable | Comparator ._______________________________________________________________________________ Is used to allow Collections.sort to work | yes | yes Can compare multiple fields | yes | yes Lives inside the class you’re comparing and serves | | as a “default” way to compare | yes | yes Can live outside the class you’re comparing | no | yes Can have multiple instances with different method names | no | yes Input arguments can be a list of | just Object| Any type Can use enums | no | yes

Я нашел лучший подход к использованию компараторов в качестве анонимных классов следующим образом:

private static void sortAccountsByPriority(List<AccountRecord> accounts) {
    Collections.sort(accounts, new Comparator<AccountRecord>() {

        @Override
        public int compare(AccountRecord a1, AccountRecord a2) {
            return a1.getRank().compareTo(a2.getRank());
        }
    });
}

Вы можете создать несколько версий таких методов прямо в классе, который вы планируете сортировать. Таким образом, вы можете иметь:

  • sortAccountsByPriority
  • sortAccountsByType
  • sortAccountsByPriorityAndType

    и т.д ...

Теперь вы можете использовать эти методы сортировки где угодно и получить повторное использование кода. Это дает мне все, что было бы сравнимо, плюс больше ... так что я не вижу никакой причины использовать сравнимо вообще.

8 голосов
/ 15 февраля 2010

Я бы сказал:

  • Если сравнение интуитивно понятно, то обязательно используйте Comparable
  • если неясно, является ли ваше сравнение интуитивно понятным, используйте Comparator, поскольку он более явный и, следовательно, более понятный для бедной души, которая должна поддерживать код
  • если возможно более одного интуитивного сравнения, я бы предпочел Comparator, возможно построение фабричным методом в классе для сравнения.
  • если сравнение специального назначения, используйте Comparator
4 голосов
/ 26 июля 2015

Следующие пункты помогут вам решить, в каких ситуациях следует использовать Comparable, а в каком Comparator:

1) Код в наличии

2) Критерии одиночной и множественной сортировки

3) Arays.sort () и Collection.sort ()

4) Как ключи в SortedMap и SortedSet

5) Больше Количество классов в зависимости от гибкости

6) Межклассовые сравнения

7) Естественный порядок

Для более подробной статьи вы можете обратиться Когда использовать сопоставимый и когда использовать компаратор

4 голосов
/ 22 мая 2018

Если сортировка объектов должна основываться на естественном порядке, тогда используйте Comparable, тогда как если сортировку нужно выполнять по атрибутам различных объектов, используйте Comparator в Java.

Основная разница между Comparable и Comparator:

+------------------------------------------------------------------------------------+
¦               Comparable                ¦                Comparator                ¦
¦-----------------------------------------+------------------------------------------¦
¦ java.lang.Comparable                    ¦ java.util.Comparator                     ¦
¦-----------------------------------------+------------------------------------------¦
¦ int objOne.compareTo(objTwo)            ¦ int compareTo(objOne, objTwo)            ¦
¦-----------------------------------------+------------------------------------------¦
¦ Negative, if objOne < objTwo            ¦ Same as Comparable                       ¦
¦ Zero,  if objOne == objTwo              ¦                                          ¦
¦ Positive,  if objOne > objTwo           ¦                                          ¦
¦-----------------------------------------+------------------------------------------¦
¦ You must modify the clas whose          ¦ You build a class separate from to sort. ¦
¦ instances you want to sort.             ¦ the class whose instances you want       ¦
¦-----------------------------------------+------------------------------------------¦
¦ Only one sort sequemce can be created   ¦ Many sort sequences can be created       ¦
¦-----------------------------------------+------------------------------------------¦
¦ Implemented frequently in the API by:   ¦ Meant to be implemented to sort          ¦
¦ String, Wrapper classes, Date, Calandar ¦ instances of third-party classes.        ¦
+------------------------------------------------------------------------------------+
4 голосов
/ 15 февраля 2010
  • Если на момент написания класса у вас есть только один вариант использования сортировки использовать сопоставимый.
  • Только когда у вас более одного Стратегия сортировки реализовать Компаратор.
...