Javaクラスは同等のものを実装する必要があるのはなぜですか?


回答:


212

これが実際のサンプルです。なお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);
}

15
多くの場合、メソッドと整合するようにオーバーライドequals(したがってhashCode)する必要があることに注意してくださいcompareTo。たとえば、クラスでを使ってうまくプレイしたい場合に必要ですTreeSet
pidge

なぜ単に戻らないのlastですか?
Anirban Nag 'tintinmj'

@ AnirbanNag'tintinmj 'は、姓が同じ場合に自動的に名でソートします。
OddDev 2015

さらに、compareToがintを返す理由とそれが何を意味するかを説明するための1つ。最も役立つ。
james.garriss

1
@ user3932000:そうです、それがすべてのインターフェースの要点です。ただし、「その他のJavaメソッド」には、ユーザーが作成したメソッドが含まれることに注意してください。実際、私はインターフェイスの大部分がユーザーのコードによって消費されると主張します。より大きなコードベースでは、「あなた自身」はすぐに「その他」になります
Enno Shioji

40

Comparableは自然な順序を定義します。これは、1つのオブジェクトを「より小さい」または「より大きい」と見なす必要がある場合に定義することを意味します。

たくさんの整数があり、それらをソートしたいとします。とても簡単です。並べ替えられたコレクションに入れるだけですよね?

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);
  }
}

コンパレータを定義することで同等のことができることに注意してください。違いは、コンパレータがオブジェクト外の順序付けロジックを定義することです。多分別のプロセスで私は郵便番号で同じオブジェクトを注文する必要があります-その場合、注文は必ずしもオブジェクトのプロパティではないか、オブジェクトの自然な順序とは異なります。外部のコンパレーターを使用して、例えば、それらをアルファベット値でソートすることにより、整数のカスタム順序を定義できます。

基本的に、順序付けロジックはどこかに存在する必要があります。それは-

  • オブジェクト自体で、それが自然に比較可能な場合(Comparable -eg integersを拡張)

  • 上記の例のように、外部コンパレータで供給されます。


良い例ですが、のTreeSet<Integer>代わりにTreeMap<Integer>する必要があり<Key,Value>ます。後者は存在しないため、ツリーマップは常に- ペアです。ところで、仮説TreeMap<District, Object>は、地区が比較可能を実装した場合にのみ機能しますよね?まだこれを理解しようとしている
phil294 '31 / 01/15

14

javadocから引用。

このインターフェイスは、それを実装する各クラスのオブジェクトに完全な順序付けを課します。この順序付けはクラスの自然順序付けと呼ばれ、クラスのcompareToメソッドはその自然比較方法と呼ばれます。

このインターフェイスを実装するオブジェクトのリスト(および配列)は、Collections.sort(およびArrays.sort)によって自動的にソートできます。このインターフェースを実装するオブジェクトは、コンパレーターを指定する必要なく、ソート済みマップのキーまたはソート済みセットの要素として使用できます。

編集:..そして重要な部分を太字にしました。


4
あなたが太字にしたもののの文章は同じくらい(それ以上ではないにしても)重要であると私は思います。
マイケルボルグワート

8

クラスが実装Comparableするということは、そのクラスから2つのオブジェクトを取得して比較できることを意味します。特定のコレクション(コレクション内の並べ替え関数)のように、オブジェクトを比較可能に保つためのいくつかのクラス(並べ替えを行うには、どのオブジェクトが「最大」かなどを知る必要があります)。


8

上記の例のほとんどは、compareTo関数で既存の比較可能なオブジェクトを再利用する方法を示しています。同じクラスの2つのオブジェクトを比較するときに独自のcompareToを実装する場合は、価格でソートするAirlineTicketオブジェクトを言います(少ない方が最初にランク付けされます)。最初にランク付け)、次のようにします:

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;            
    }
}

6

複数のフィールド比較を実装する簡単な方法は、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);
  }
}

3

たとえば、並べ替えられたコレクションまたはマップが必要な場合


Fernandoの意味は、Comparableを実装する「もの」をソート済みコンテナークラスに格納すると、ソート済みコンテナークラスはそれらの「もの」を自動的に並べ替えることができます。
Ian Durkan

2

Comparableは、クラスのインスタンスを比較するために使用されます。インスタンスを比較するcompareTo方法(属性)を知るためにメソッドを実装する必要があるのは、さまざまな方法でインスタンスを比較できるためです。

Dog クラス:

package test;
import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        Dog d1 = new Dog("brutus");
        Dog d2 = new Dog("medor");
        Dog d3 = new Dog("ara");
        Dog[] dogs = new Dog[3];
        dogs[0] = d1;
        dogs[1] = d2;
        dogs[2] = d3;

        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * brutus
         * medor
         * ara
         */

        Arrays.sort(dogs, Dog.NameComparator);
        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * ara
         * medor
         * brutus
         */

    }
}

Main クラス:

package test;

import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        Dog d1 = new Dog("brutus");
        Dog d2 = new Dog("medor");
        Dog d3 = new Dog("ara");
        Dog[] dogs = new Dog[3];
        dogs[0] = d1;
        dogs[1] = d2;
        dogs[2] = d3;

        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * brutus
         * medor
         * ara
         */

        Arrays.sort(dogs, Dog.NameComparator);
        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * ara
         * medor
         * brutus
         */

    }
}

以下は、Javaで比較機能を使用する方法の良い例です。

http://www.onjava.com/pub/a/onjava/2003/03/12/java_comp.html?page=2


2

Comparableインターフェースを実装するときは、methodを実装する必要がありますcompareTo()。たとえば、ArrayListクラスのソート方法を使用するために、オブジェクトを比較する必要があります。オブジェクトを比較してソートできるようにする方法が必要です。したがってcompareTo()ArrayListsortメソッドで使用できるように、クラスにはカスタムメソッドが必要です。このcompareTo()メソッドは-1,0,1を返します。

Java Head 2.0の対応する章を読んだところですが、まだ学習中です。


1

わかりましたが、compareTo()比較可能なインターフェイスを実装せずにメソッドを定義しないのはなぜですか たとえばCitynameand temperatureおよびandで定義されたクラス

public int compareTo(City theOther)
{
    if (this.temperature < theOther.temperature)
        return -1;
    else if (this.temperature > theOther.temperature)
        return 1;
    else
        return 0;
}

これは動作しません。同等のものを実装しないと、クラスキャストの例外が発生します
Karan Ahuja
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.