Java 클래스가 비슷한 것을 구현해야하는 이유는 무엇입니까? 구현 하는

왜 Java가 Comparable사용됩니까? 누군가 Comparable클래스에서 구현 하는 이유는 무엇 입니까? 비슷한 것을 구현해야하는 실제 사례는 무엇입니까?



답변

실제 샘플은 다음과 같습니다. 그 참고 String도 구현을 Comparable.

class Author implements Comparable<Author>{
    String firstName;
    String lastName;

    @Override
    public int compareTo(Author other){
        // compareTo should return < 0 if this is supposed to be
        // less than other, > 0 if this is supposed to be greater than 
        // other and 0 if they are supposed to be equal
        int last = this.lastName.compareTo(other.lastName);
        return last == 0 ? this.firstName.compareTo(other.firstName) : last;
    }
}

나중..

/**
 * List the authors. Sort them by name so it will look good.
 */
public List<Author> listAuthors(){
    List<Author> authors = readAuthorsFromFileOrSomething();
    Collections.sort(authors);
    return authors;
}

/**
 * List unique authors. Sort them by name so it will look good.
 */
public SortedSet<Author> listUniqueAuthors(){
    List<Author> authors = readAuthorsFromFileOrSomething();
    return new TreeSet<Author>(authors);
}

답변

비교는 자연 순서를 정의합니다. 이것이 의미하는 것은 하나의 객체가 “보다 작음”또는 “보다 큼”으로 간주되어야 할 때이를 정의한다는 것입니다.

여러 개의 정수가 있고 정렬하려고한다고 가정하십시오. 꽤 쉬운 방법입니다. 정렬 된 컬렉션에 넣으면됩니다.

TreeSet<Integer> m = new TreeSet<Integer>();
m.add(1);
m.add(3);
m.add(2);
for (Integer i : m)
... // values will be sorted

그러나 이제 정렬이 의미가 있지만 정의되지 않은 사용자 정의 객체가 있다고 가정합니다. 인구 밀도가있는 우편 번호로 지구를 나타내는 데이터가 있고 밀도별로 정렬하려고한다고 가정 해 보겠습니다.

public class District {
  String zipcode;
  Double populationDensity;
}

이제 그것들을 정렬하는 가장 쉬운 방법은 Comparable을 구현하여 자연스러운 순서로 정의하는 것입니다. 즉, 이러한 객체가 정렬되도록 정의 된 표준 방법이 있습니다. :

public class District implements Comparable<District>{
  String zipcode;
  Double populationDensity;
  public int compareTo(District other)
  {
    return populationDensity.compareTo(other.populationDensity);
  }
}

비교기를 정의하여 동등한 작업을 수행 할 수 있습니다. 차이점은 비교기 가 객체 외부의 순서 논리를 정의한다는 것 입니다. 별도의 프로세스에서 우편 번호로 동일한 객체를 주문해야합니다.이 경우 순서는 반드시 객체의 속성 일 필요는 없으며 객체의 자연 순서와 다릅니다. 외부 비교기를 사용하여 예를 들어 사전 순으로 정렬하여 정수에 대한 사용자 정의 순서를 정의 할 수 있습니다.

기본적으로 순서 논리는 어딘가에 존재해야합니다. 그것은 가능하다 –

  • 객체 자체에서 자연스럽게 비교 가능한 경우 (예 : 정수 확장)

  • 위의 예와 같이 외부 비교기에서 제공됩니다.


답변

javadoc에서 인용;

이 인터페이스는이를 구현하는 각 클래스의 객체에 총 정렬을 부과합니다. 이 순서를 클래스의 자연 순서라고하며 클래스의 compareTo 메소드를 자연 비교 방법이라고합니다.

이 인터페이스를 구현하는 객체의 목록 (및 배열)은 Collections.sort (및 Arrays.sort)로 자동 정렬 할 수 있습니다. 이 인터페이스를 구현하는 객체는 비교기를 지정할 필요없이 정렬 된 맵의 키 또는 정렬 된 세트의 요소로 사용할 수 있습니다.

편집 : .. 그리고 중요한 비트를 굵게 표시했습니다.


답변

클래스가 구현 Comparable한다는 것은 해당 클래스에서 두 개의 객체를 가져 와서 비교할 수 있다는 것을 의미합니다. 개체를 순서대로 정렬하는 특정 컬렉션 (컬렉션의 정렬 함수)과 같은 일부 클래스는 정렬하기 위해 어떤 개체가 “가장 큰”개체인지 알아야합니다.


답변

위의 예제 대부분은 compareTo 함수에서 기존의 비교 가능한 객체를 재사용하는 방법을 보여줍니다. 같은 클래스의 두 객체를 비교할 때 고유 한 compareTo를 구현하려면 가격별로 정렬하려는 AirlineTicket 객체 (첫 번째 순위는 낮음)와 중간 기착 횟수 (더 적은 것은 1 위), 다음을 수행합니다.

class AirlineTicket implements Comparable<Cost>
{
    public double cost;
    public int stopovers;
    public AirlineTicket(double cost, int stopovers)
    {
        this.cost = cost; this.stopovers = stopovers ;
    }

    public int compareTo(Cost o)
    {
        if(this.cost != o.cost)
          return Double.compare(this.cost, o.cost); //sorting in ascending order. 
        if(this.stopovers != o.stopovers)
          return this.stopovers - o.stopovers; //again, ascending but swap the two if you want descending
        return 0;
    }
}

답변

여러 필드 비교를 구현하는 쉬운 방법은 Guava의 ComparisonChain 을 사용하는 것입니다.

   public int compareTo(Foo that) {
     return ComparisonChain.start()
         .compare(lastName, that.lastName)
         .compare(firstName, that.firstName)
         .compare(zipCode, that.zipCode)
         .result();
   }

대신에

  public int compareTo(Person other) {
    int cmp = lastName.compareTo(other.lastName);
    if (cmp != 0) {
      return cmp;
    }
    cmp = firstName.compareTo(other.firstName);
    if (cmp != 0) {
      return cmp;
    }
    return Integer.compare(zipCode, other.zipCode);
  }
}