48

インスタンス化時にカスタム コンパレータを受け取る Java TreeSet の機能に似たものを探していたので、オブジェクトのデフォルトの等価性 (およびハッシュ コード) 基準を使用する必要はありませんでした。

私が思いついた最も近い方法は、オブジェクトをプライベート カスタム クラスでラップすることでしたが、それはハッキリしているように思えます :( これは、プログラミング時に一種の繰り返しのテーマになってしまうため、使用できるものが既にあるのではないかと考えていました。多分コモンズライブラリで?

ありがとう

4

3 に答える 3

18

いいえ、使用することになっているソリューションを正確に見つけました。

であってもTreeSet、互換性のない比較基準を使用することは嫌われequalsています。

ソートされたセットが Set インターフェースを正しく実装するためには、(明示的なコンパレータが提供されているかどうかに関係なく) ソートされたセットによって維持される順序付けが equals と一致している必要があることに注意してください。

Apache Commons については知りませんが、Guava Equivalenceを使用して目的を達成することはできますが、Guava はこの種のリクエストを具体的に 拒否しました。

Equivalence<T> equivalence = new Equivalence<T>() {
    @Override
    protected boolean doEquivalent(T a, T b) {
        return CustomComparator.equals(a, b);
    }

    @Override
    protected int doHash(T item) {
        return CustomHashCodeGenerator.hashCode(item);
    }
};
List<T> items = getItems();
Set<Equivalence.Wrapper<T>> setWithWrappedObjects = items.stream()
    .map(item -> equivalence.wrap(item))
    .collect(Collectors.toSet());
于 2013-02-14T17:20:36.560 に答える
4

カスタムの等価ロジックを可能にするサードパーティのコレクション フレームワークがいくつかあります。これは、ソースを変更できないオブジェクトの等価性をオーバーライドするのに最適です。

Trove のマップ/セットは、カスタム ハッシュ戦略の使用をサポートしているため、入力データの特性に基づいてコレクションを調整できます。この機能により、Object.hashCode() をオーバーライドできない場合にハッシュ関数を定義することもできます。

これを実現するには、標準的な修正が必要なすべての型で、HE-Collection インターフェース EqualsAndHashCorrection を実装する必要があります。このインターフェースは、メソッド hashCodeInHeCollection() および equalsInHeCollection(Object) を定義します。これらは、正しく実装されていないメソッド hashCode() および equals(Object) の修正として機能します。

于 2013-02-14T18:11:32.960 に答える
3

Trees( TreeMapTreeSet) 追加するオブジェクトのいずれかを使用する場合は、正しいです。実装する必要がありますComparable

プリミティブ型の場合、Java がこれを解決してくれます。
カスタム オブジェクトの場合、次の 3 つの可能性があります。

  1. オブジェクトの 1 つは、プリミティブ型または既に実装されている型の一意の ID を既に持っていますcompareTo()( などString)。次に、他の値が同等であることが重要でない場合は、compareTo にこのフィールドを使用します。(ただし、equals()この 1 つのフィールドのみを使用する必要もあります)

  2. Apache から使用EqualsBuilder: これはリフレクションで動作し、最速のソリューションではありません

  3. 自分で書いて、それを行う方法のチュートリアルを読んでください:例:

Josh Bloch: 効果的な Java 第 2 版

ただし、等号契約に違反しないように、 と は互換性がなければならない (および も)equals()ことcompareTo()を忘れないでください。hashCode()(コントラクト自体はあまり理解できませんが、いずれかのチュートリアルをフォローすると明確になります。)

または、すべてを忘れて、 , を使用しHashSetますHashMap

于 2013-02-14T17:30:28.680 に答える