5

equalsカスタムコンパレータを実装する場合、それ以外にオーバーライドすることは良い習慣と見なされcompareますか?
さらに、?の定義済みの契約はありComparatorますか?

4

5 に答える 5

4

コンパレータのjavadocには次のように記載されています。

コンパレータcによって要素Sのセットに課される順序は、c.compare(e1、e2)== 0がすべてのe1に対してe1.equals(e2)と同じブール値を持っている場合に限り、equalsと一致すると言われます。およびSのe2。

ソートされたセット(またはソートされたマップ)を順序付けるために、equalsと矛盾する順序を課すことができるコンパレータを使用する場合は注意が必要です。明示的なコンパレータcを持つソートされたセット(またはソートされたマップ)が、セットSから引き出された要素(またはキー)で使用されると仮定します。 「奇妙に」振る舞う。特に、ソートされたセット(またはソートされたマップ)は、等しいという観点から定義されたセット(またはマップ)の一般的な契約に違反します。

したがって、答えは「はい」です。これは良い習慣です(少なくとも最初の質問については)。

于 2012-10-04T09:20:15.990 に答える
4

Comparatorのコントラクトは、そのjavadocで定義されています。特に:

ソートされたセット(またはソートされたマップ)を順序付けるために、equalsと矛盾する順序を課すことができるコンパレータを使用する場合は注意が必要です。明示的なコンパレータcを持つソートされたセット(またはソートされたマップ)が、セットSから引き出された要素(またはキー)で使用されると仮定します。 「奇妙に」振る舞う。特に、ソートされたセット(またはソートされたマップ)は、等しいという観点から定義されたセット(またはマップ)の一般的な契約に違反します。

通常、2つのオブジェクトがパースペクティブからは等しいが、equalsパースペクティブからは等しくない場合compareTo、両方のオブジェクトをキーとしてTreeMapに格納できます。これは、直感的でない動作につながる可能性があります。また、特定の状況で意図的に行うこともできます。

たとえば、この回答は、 equalsとcompareToが矛盾していることが望ましい例を示しています。

于 2012-10-04T09:23:16.677 に答える
3

平等をテストしていると感じた場合にのみ、等号をオーバーライドする必要があると思います。多くの場合、コンパレータを作成すると、オブジェクト内のプロパティが比較され、これらのプロパティでcompareToを引き続き使用します。

例えば

public class ToCompare {

    public static final Comparator<ToCompare> ID_COMPARATOR = new Comparator(){
        @Override
        public int compare(ToCompare o1, ToCompare o2) { 
             return o1.id.compareTo(o2.id);
        }
    }
    private Integer id;
    //... other fields here

}

私はこれらのコンパレータをオブジェクトに格納する傾向があります。これらのコンパレータへのパブリック静的最終フィールドは、このオブジェクトをソートする可能性のある任意のコードからアクセスできます。オブジェクトが更新された場合(フィールドが追加/削除された場合)、コード検索の問題をすべて調べるのではなく、コンパレータに問題があるかどうかをすぐに確認できます。

于 2012-10-04T09:21:14.150 に答える
1

はい。Comparatorのjavadocで提案されて いるように、それはあなたのニーズに依存すると思います。

たとえば、コンパレータcを使用して空のTreeSetに(a.equals(b)&& c.compare(a、b)!= 0)となる2つの要素aとbを追加するとします。Set.addメソッドの仕様に反していても、aとbはツリーセットの観点からは同等ではないため、2番目のadd操作はtrueを返します(ツリーセットのサイズが大きくなります)。

ただし、特定のリストを並べ替えるだけでよい以下の例を検討すると、並べ替える必要がない場合があります。

Employee2つのプロパティを持つidクラスの例を見てみましょうname

class Employee {
    int id;// sample so access not considered
    String name;// sample so access not considered
}

リストを並べ替えるオプションが2つあるとしidますname。これを実現するには、2つのコンパレータを実装する必要があります。1つは名前で比較しid、もう1つcomparesは名前で比較します。

今、私がコンパレータを実装したい場合id、そのタイプはintラッパータイプでIntegerあり、メソッドをInteger提供するので、それを使用します。compareTo

の場合も同様ですStringcompareこのように、あなたは書くことやcompareTo方法についてほとんど心配する必要はありません。

compare私は常にオブジェクトのプロパティに組み込まれたメソッドを使用するので、メソッドを作成するときに考える必要はほとんどありません。

class EmpIdComparator implements Comparator<Employee> {

    @Override
    public int compare(Employee o1, Employee o2) {
        return Integer.valueOf(o1.id).compareTo(o2.id);// Make use of
                                                        // existing
                                                        // comparators
                                                        // provided by java
    }

}

class EmpNameComparator implements Comparator<Employee> {

    @Override
    public int compare(Employee o1, Employee o2) {
        return o1.name == null ? o2.name == null ? 0 : 1 : o1.name
                .compareTo(o2.name);// Make use of
        // existing
        // comparators
        // provided by java
    }

}
于 2012-10-04T09:46:42.283 に答える
0

他の答えは要点を見逃しているように感じますComparator。'scompare-methodは2つの指定されたパラメーターを比較し、Comparator'sequals-methodはComparatorそれ自体を別のオブジェクトと比較します。

Comparator#equals少なくとも新しいJDKのjavadocは、それを詳細に説明しています。

/**
 * Indicates whether some other object is &quot;equal to&quot; this
 * comparator.  This method must obey the general contract of
 * {@link Object#equals(Object)}.  Additionally, this method can return
 * <tt>true</tt> <i>only</i> if the specified object is also a comparator
 * and it imposes the same ordering as this comparator.  Thus,
 * <code>comp1.equals(comp2)</code> implies that <tt>sgn(comp1.compare(o1,
 * o2))==sgn(comp2.compare(o1, o2))</tt> for every object reference
 * <tt>o1</tt> and <tt>o2</tt>.<p>
 *
 * Note that it is <i>always</i> safe <i>not</i> to override
 * <tt>Object.equals(Object)</tt>.  However, overriding this method may,
 * in some cases, improve performance by allowing programs to determine
 * that two distinct comparators impose the same order.
 *
 * @param   obj   the reference object with which to compare.
 * @return  <code>true</code> only if the specified object is also
 *          a comparator and it imposes the same ordering as this
 *          comparator.
 * @see Object#equals(Object)
 * @see Object#hashCode()
 */
boolean equals(Object obj);

そのため、のequals-methodをオーバーライドすることはほとんど役に立ちませんComparatorComparableしかし、違うでしょう。

于 2015-03-23T10:25:09.890 に答える