6

Can StringBuffer objects be keys in TreeSet in Java?に関するこのコメントを見つけました。

「Maps in Java (多かれ少なかれ) で使用される識別戦略は 2 つあります。

ハッシュ: 入力 "Foo" は、配列内のインデックスに一意にアクセスする数値を生成するために、可能な限り最善の試みに変換されます。(純粋主義者の皆さん、私を悪用しないでください。意図的に単純化しています)。このインデックスは、値が格納される場所です。「Foo」と「Bar」が実際に同じインデックス値を生成する可能性があります。つまり、両方が同じ配列位置にマップされる可能性があります。明らかにこれは機能しないため、「equals()」メソッドの出番です。あいまいさを解消するために使用されます

比較: 比較方法を使用することにより、この余分な明確化ステップは必要ありません。なぜなら、比較によって最初からこの衝突が発生することはないからです。"Foo" が等しい唯一のキーは "Foo" です。ただし、「equals()」を compareTo() == 0; として定義することができる場合は、本当に良い考えです。一貫性のために。要件ではありません。」

私の質問は次のとおりです。クラスが同等のものを実装している場合、オブジェクトをハッシュコレクションのキーとして使用するために equals および hashcode メソッドをオーバーライドする必要がないということですか。例えば

class Person implements Comparable<Person> {
     int id;
     String name;

     public Person(int id, String name) {
        this.id=id;
        this.name=name;
     }

    public int compareTo(Person other) {
      return this.id-other.id;
    }
}

さて、Hashable コレクションで Person オブジェクトを使用できますか?

4

5 に答える 5

6

あなたが持ってきた記事は で話題になっていTreeSetます。ツリー セットは、各ノードが、ツリー内に既に存在する他の値と比較して、その値によって定義された場所を持つツリーです。

ahashTableはキーと値のペアをハッシュ テーブルに格納します。Hashtable を使用する場合、キーとして使用するオブジェクトと、そのキーにリンクする値を指定します。次に、キーがハッシュされ、結果のハッシュ コードがテーブル内で値が格納されるインデックスとして使用されます。

Hashableとの違いTreeSetは、treeset は を必要hashCodeとしないということです。アイテムをツリーの左または右に移動する必要があるかどうかを知る必要があるだけです。そのためには、Compare を使用できますが、それ以上は使用できません。

hashTable では、比較で十分です。これは、ビルドが異なるためです。各オブジェクトは、コレクション内の既存のアイテムと比較するのではなく、ハッシュすることによってセルに到達します。

答えはノーです。Personハッシュテーブルで使用できますcompareTo。あなたはオーバーライドする必要がhashCode()ありequals()、そのために

また、ハッシュテーブルに関するこの記事を読むことをお勧めします

于 2013-08-22T23:49:55.493 に答える
2

HashTable は equals と hashCode を使用します。すべてのクラスにはこれらのメソッドがあります。それらを実装しない場合は、それらを継承します。

それらを実装する必要があるかどうかは、継承されたバージョンが目的に適しているかどうかによって異なります。特に、Person にはスーパークラスが指定されていないため、Object メソッドを継承します。つまり、Person オブジェクトはそれ自体とのみ等しいということです。

2 つの異なる Person オブジェクトを HashTable キーとして同等に扱う必要がありますか?

于 2013-08-22T23:59:18.767 に答える
0

クラスが を実装している場合、クラスComparableのインスタンスが何らかの値を表していることが示唆されます。一般に、クラスが値をカプセル化する場合、同じ値を保持する 2 つの異なるインスタンスが存在する可能性があり、したがって同等と見なされます。個別のオブジェクト インスタンスが同等と見なされる唯一の方法は、それらがequalsandをオーバーライドhashCodeすることであるため、これは、実装するものがComparableオーバーライドする必要があることを意味し、動作するカプセル化された値がグローバルに一意equalshashCode ない限りcompare(個別のインスタンスが同等と見なされるべきではないことを意味します) )。

簡単な例として、クラスCreationRankに type のフィールドが含まれているとしlongます。インスタンスが作成されるたびに、そのメンバーは singleton からフェッチされた値に設定され、そのフィールドAtomicLongComparable使用してオブジェクトを作成順にランク付けします。クラスの 2 つの異なるインスタンスが同じを報告することはありませんCreationRank。したがって、x.equals(y)true になる唯一の方法は、 ifxy同じオブジェクト インスタンスを参照することです。これは、デフォルトのequalsとが機能する方法とまったく同じですhashCode

ところで、x.compare(y)ゼロを返すということは、通常、それが true を返すことを意味するはずx.equals(y)です。これは、オブジェクトがランク付けできるプロパティとできないプロパティをカプセル化する場合に当てはまります。たとえば、をカプセル化する仮説型とインターフェースの実装を考えてみましょう。このようなものは、カプセル化された日付と時刻に基づいてランク付けできますが、日付と時刻が同じでアクションが異なる 2 つのアイテムをランク付けする賢明な方法はない場合があります。明らかに同等ではないアイテムを「同等」と呼ぶ必要があるふりをするよりも、ゼロを報告する一方で偽を報告する方が理にかなっています。x.equals(y)x.compare(y)FutureActionDateTimeDoSomethingequalscompare

于 2013-08-23T21:08:14.783 に答える
0

TreeSet には、ツリーの右または左に値を追加するために Comparable が必要です。HashMap には、オブジェクト クラスから利用できる equals() および Hashcode() メソッドが必要ですが、目的に合わせてオーバーライドする必要があります。

于 2013-08-23T01:47:49.760 に答える