Когда использовать Comparable и Comparator

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

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

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

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

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

20 ответов


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

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

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


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

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


использовать Comparable:

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

использовать Comparator :

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

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

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

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

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

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

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

пример:

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)
    }
}
  • для подгонянный сортировать мы идем для компаратора @сравниваем(О1, О2) для другого сценарии мы идем для comparable @compareTo (o1), без изменения кода, если мы хотим отсортировать более одного поля, мы используем comparator.

на Java 8 Лямбда : Компаратор обратитесь к моему сообщению.


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

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

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

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


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

    etc...

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


Я бы сказал так:

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

  • Если в момент написания класса у вас есть только один вариант использования сортировки используйте Comparable.
  • только если у вас больше одного стратегии сортировки реализовать Компаратор.

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

1) Код Availabilty

2) Один Против Нескольких Критериев Сортировки

3) Arays.сортировка () и сбор.sort ()

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

5) большее количество классов по сравнению с гибкостью

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

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

дополнительные подробную статью вы можете сослаться когда использовать comparable и когда использовать comparator


здесь был аналогичный вопрос:когда класс должен быть сопоставимым и / или компаратором?

Я бы сказал следующее: Реализуйте сопоставимое для чего-то вроде естественного упорядочения, например, на основе внутреннего ID

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


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

пример:

Class Employee{
private int id;
private String name;
private String department;
}

сортировка естественного порядка будет основана на id, потому что она будет уникальной, а сортировка пользовательского порядка g будет именем и отделом.

Refrences:
когда класс должен быть сопоставимым и / или компаратором? http://javarevisited.blogspot.com/2011/06/comparator-and-comparable-in-java.html


сравним:
Всякий раз, когда мы хотим сохранить только однородные элементы и по умолчанию требуется естественный порядок сортировки, мы можем перейти к реализации класса comparable интерфейс.

компаратор:
Всякий раз, когда мы хотим хранить однородные и гетерогенные элементы, и мы хотим Сортировать по умолчанию настроенный порядок сортировки, мы можем пойти на comparator интерфейс.


Если сортировка объектов должна основываться на естественном порядке, используйте 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.        ¦
+------------------------------------------------------------------------------------+

очень простой подход состоит в том, чтобы предположить, что рассматриваемый класс сущности будет представлен в базе данных, а затем в таблице базы данных вам понадобится индекс, состоящий из полей класса сущности? Если ответ да, то реализуйте comparable и используйте поле(ы) индекса для естественного порядка сортировки. Во всех остальных случаях используйте компаратор.


Мне нужно было Сортировать по дате.

Итак, я использовал Comparable, и он работал легко для меня.

public int compareTo(GoogleCalendarBean o) {
    // TODO Auto-generated method stub
    return eventdate.compareTo(o.getEventdate());
}

одно ограничение с Comparable заключается в том, что они не могут использоваться для коллекций, отличных от List.


Если у вас есть класс, лучше пойти с сопоставимо. Вообще компаратор используется, если у вас нет класса, но вы должны использовать его TreeSet или TreeMap потому что компаратор можно передать как параметр в conctructor TreeSet или TreeMap. Вы можете увидеть, как использовать Comparator и Comparable в http://preciselyconcise.com/java/collections/g_comparator.php


меня попросили сортировку определенного диапазона чисел в лучшее, чем время nlogn в одном из интервью. (Не используя подсчет сортировки)

реализация сопоставимого интерфейса над объектом позволяет неявной сортировке algos использовать переопределенный метод compareTo для упорядочения элементов сортировки, и это будет линейное время.


  • компаратор для многих критериев сравнения
  • сравним, когда у вас есть только один критерий.

Comparable-это естественный порядок сортировки по умолчанию для числовых значений по возрастанию, а для строк-в алфавитном порядке. например:

Treeset t=new Treeset();
t.add(2);
t.add(1);
System.out.println(t);//[1,2]

Comparator-это пользовательский порядок сортировки, реализованный в пользовательском классе myComparator путем переопределения метода compare например:

Treeset t=new Treeset(new myComparator());
t.add(55);
t.add(56);
class myComparator implements Comparator{
public int compare(Object o1,Object o2){
//Descending Logic
}
}
System.out.println(t);//[56,55]

моя аннотация lib для реализации Comparable и Comparator:

public class Person implements Comparable<Person> {         
    private String firstName;  
    private String lastName;         
    private int age;         
    private char gentle;         

    @Override         
    @CompaProperties({ @CompaProperty(property = "lastName"),              
        @CompaProperty(property = "age",  order = Order.DSC) })           
    public int compareTo(Person person) {                 
        return Compamatic.doComparasion(this, person);         
    }  
}

нажмите на ссылку, чтобы увидеть больше примеров. http://code.google.com/p/compamatic/wiki/CompamaticByExamples