[java] Comparable 및 Comparator를 사용하는 경우

필드에서 정렬해야하는 개체 목록이 있습니다 (예 : Score). 별다른 생각없이 Comparator를 구현하는 새로운 클래스를 작성했습니다.

이제 이것을 돌아 보면 Comparator를 구현하는 새 클래스를 만드는 대신 내 클래스가 Comparable을 구현해야하는지 궁금합니다. 점수는 개체가 정렬되는 유일한 필드입니다.

  1. 내가 실천으로 받아 들일 수있는 일을 한 것은 무엇입니까?

  2. 올바른 접근 방식은 “먼저 클래스가 Comparable (자연 순서를 위해)을 구현하도록하고 대체 필드 비교가 필요한 경우 Comparator를 구현하는 새 클래스를 만듭니다”입니까?

  3. 위의 (2)가 참이라면 Comparable 클래스를 구현 한 후에 만 ​​Comparator를 구현해야 함을 의미합니까? (원래 수업을 소유하고 있다고 가정).



답변

나는 그것이 클래스를 정렬하는 명백한 자연스러운 방법이고, 누구든지 클래스를 정렬해야 할 필요가 있다면, 객체는 Comparable을 구현해야한다고 말하고 싶습니다.

그러나 정렬이 클래스의 비정상적인 사용이거나 정렬이 특정 사용 사례에서만 의미가 있다면 비교기가 더 나은 옵션입니다.

다른 말로, 클래스 이름이 주어지면 비교 가능한 정렬 방법이 분명합니까? 아니면 javadoc을 읽어야합니까? 후자의 경우 향후 모든 정렬 사용 사례에 비교기가 필요하며,이 시점에서 비교 가능을 구현하면 클래스 사용자의 속도를 높이 지 않고 속도를 늦출 수 있습니다.


답변

문제가되는 개체 Comparable기본 (자연) 순서 지정 동작 을 정의하려는 경우 사용 합니다 . 일반적인 방법은이를 위해 개체의 기술 또는 자연 (데이터베이스?) 식별자를 사용하는 것입니다.

제어 가능한 외부 정렬 동작 Comparator을 정의하려는 경우 사용 합니다 . 기본 정렬 동작을 재정의 할 수 있습니다.


답변

사용 Comparable:

  • 개체가 귀하의 통제에있는 경우.
  • 비교 행동이 주요 비교 행동 인 경우.

사용 Comparator:

  • 개체가 제어 범위 밖에 있고 구현할 수없는 경우 Comparable.
  • 기본 (으로 지정됨 Comparable) 동작 과 다른 동작을 비교하려는 경우 .

답변

유사한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 인터페이스를 구현할 수 있습니다.

예:

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)로 이동합니다. 하나 이상의 필드를 정렬하려면 코드를 변경하지 않고 비교기를 사용합니다.

를 들어 자바 8 람다 : 비교기는 내 게시물을 참조하십시오.


답변

동일한 클래스의 인스턴스를 비교할 때 Comparable을 사용해야합니다.

비교기는 다른 클래스의 인스턴스를 비교하는 데 사용할 수 있습니다.

Comparable은 객체에 대한 자연스러운 순서를 정의해야하는 클래스에 의해 구현됩니다. Like String은 Comparable을 구현합니다.

다른 정렬 순서를 원할 경우 비교기를 구현하고 두 인스턴스를 비교하는 자체 방법을 정의 할 수 있습니다.


답변

객체 정렬이 자연스러운 순서를 기반으로해야하는 경우 Comparable을 사용하고 다른 객체의 속성에 대해 정렬을 수행해야하는 경우 Java에서 Comparator를 사용하십시오.

Comparable과 Comparator의 주요 차이점 :

+------------------------------------------------------------------------------------+
¦               Comparable                ¦                Comparator                ¦
¦-----------------------------------------+------------------------------------------¦
¦ java.lang.Comparable                    ¦ java.util.Comparator                     ¦
¦-----------------------------------------+------------------------------------------¦
¦ int objOne.compareTo(objTwo)            ¦ int compare(objOne, objTwo)              ¦
¦-----------------------------------------+------------------------------------------¦
¦ Negative, if objOne < objTwo            ¦ Same as Comparable                       ¦
¦ Zero,  if objOne == objTwo              ¦                                          ¦
¦ Positive,  if objOne > objTwo           ¦                                          ¦
¦-----------------------------------------+------------------------------------------¦
¦ You must modify the class whose         ¦ You build a class separate from to sort. ¦
¦ instances you want to sort.             ¦ the class whose instances you want       ¦
¦-----------------------------------------+------------------------------------------¦
¦ Only one sort sequence 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, Calendar ¦ instances of third-party classes.        ¦
+------------------------------------------------------------------------------------+


답변

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

    기타…

이제 어디서나 이러한 정렬 방법을 사용하고 코드를 재사용 할 수 있습니다. 이것은 나에게 비교 가능한 모든 것을 제공하고 더 많은 것을 제공합니다 … 그래서 나는 비교할 이유를 전혀 보지 못합니다.