Когда использовать сопоставимый и компаратор


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

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

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

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

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

20 94

20 ответов:

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

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

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

использовать 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)

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

  • способен сравнивать любые два объекта одного типа.
  • С помощью этого мы можем реализовать many sort sequence и назовите каждый из них, основываясь на свойствах экземпляров. Например: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 Lambda: Comparator см. мой пост.

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

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

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

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

компаратор делает все, что сопоставимый делает, плюс больше.

| | 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
  • Если неясно, является ли ваше сравнение интуитивно понятным, используйте компаратор, поскольку это больше явный и, следовательно, более ясный для бедной души, которая должна поддерживать код
  • Если возможно более одного интуитивного сравнения, я бы предпочел компаратор, возможно, построить заводским методом в классе для сравнения.
  • если сравнение специального назначения, использовать компаратор
  • Если в момент написания класса у вас есть только один вариант использования сортировки используйте сопоставимые.
  • только если у вас есть более одного стратегию сортировки реализуют а Компаратор.

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

1) Наличие Кода

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

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

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

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

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

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

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

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

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

Если у вас есть класс лучше пойти с сопоставимо. Вообще компаратор используется, если вы не являетесь владельцем класса, но вы должны использовать его a TreeSet или TreeMap потому что компаратор может быть передан в качестве параметра в конструкторе 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 путем переопределения метода сравнения например:

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