3

私の知る限り、SortedMapまたはなどは、等式(、 )をチェックするために型に(ではなく)をSortedSet使用します。compareToequalsComparable<?>containscontainsKey

しかし、特定のタイプが概念的に同等であるが、比較できない場合はどうなるでしょうか。
(ハッシュコード、メモリアドレス、...)

を宣言しComparator<?>、メソッドをオーバーライドする必要がありますint compareTo(T o1, To2)。OK、等しいと見なされるインスタンスに対して0を返すことができます。しかし、不規則な場合、注文が明確でない場合は何を返しますか?

SortedMapまたはSortedSetを同等に使用するアプローチは、概念的には)同等のタイプではありませんか?

ありがとうございました!

編集:
並べ替えて保存したくないのですが、「通常の」マップとセットを使用すると、平等の動作を「オーバーライド」できませんでした。

編集2:
なぜ私は単にオーバーライドできないのですかequals(...)
私は外国のクラスの平等の振る舞いを変更する必要があります。編集できません。

編集3:
.NETについて考えてみてください:それらは、同等の動作に触れることなく、同等の動作を変更するIEquatableインターフェイスを備えています。

編集4:等しい場合は0を返し、等しくない場合は1を返す
ことはできませんか?compareTo大きな問題は何ですか?いくつかのテストをドーム型にしましたが、SortedMap/SortedSetがインスタンスのペアでcompareToを一度呼び出したようです。はい、順序は意味がありませんが、なぜそれが私の問題になるのですか?注文は必要ありません。*私は平等行動を変える必要があります。悲しいことに、ほとんどの人はこれを理解できません。
注:等しくないインスタンスに対して1を返すという概念は、間違っていることが証明されました。

編集5:
平等を変える-外国のクラスの振る舞いは悪い概念ですか?もちろん?私はそうは思いません:なぜ私は外国のクラスの比較行動を使用して変更することを許可されているのComparatorですか?

編集6:カスタムクラスでキータイプをラップするというアイデアに感謝
します。このようにして、equalsとhashCodeをオーバーライドして、equality-behaviorを変更できます。Mark Peterswaxwing

4

13 に答える 13

10

いいえ、SortedMap または SortedSet を同等であるが比較できない型で使用するのは恐ろしい考えです。それらが本質的に比較できない場合、またはコンパレーターを介して比較できない場合は、SortedSet で使用しないでください。Sorted は順序があることを意味します。つまり、2 つの項目を比較してどちらが「少ない」かを確認できます。

HashMap/Set を使用するだけです。

あなたの編集#2に編集

equals を適切にオーバーライドできない場合は、どこかで非常に悪い設計になっています。達成しようとしていることについて、より多くの情報を提供する必要があります。

あなたの編集#3に編集

Java では、equalsを変更しても、同等の動作は変更されません。それを達成するためのインターフェースは必要ありません。

あなたの編集#4に編集

いいえ、等しくない要素に対して 1 を返すことはできません!!

SortedSet は、比較を使用してセット内の要素を見つけます。同等のインターフェースには特定の要件があります。あなたが壊しているのは、 if A.compareTo(B) > 0、 then 必然B.compareTo(A) < 0. あなたはそれを破っているので、セットのあとがきで要素を見つけることができなくなります。

public static void main(String[] args) throws Exception {
    SortedSet<MyClass> set = new TreeSet<MyClass>();
    MyClass one = new MyClass(1);
    set.add(one);
    set.add(new MyClass(2));
    set.add(new MyClass(3));
    System.out.println(set.contains(one));
}
private static class MyClass implements Comparable<MyClass> {
    private final int data;
    private MyClass(int data) { this.data = data; }
    public int compareTo(MyClass o) { return (data == o.data ? 0 : 1); }
}

このコードは を出力falseするため、明らかにコンパレーターが Set のセマンティクスを壊しています。

于 2010-06-18T13:20:09.867 に答える
10

代わりに、外部クラスを独自のクラスにラップすることを検討してください。

public class Foreign {
  // undesired equals() and hashCode() implementation
}


public class ForeignWrapper {
   private Foreign foreign;

   public ForeignWrapper(Foreign foreign) {
      this.foreign = foreign;
   }

   public void equals() {
       // your equals implementation, using fields from foreign
   }

   public int hashCode() {
       // your hashCode implementation, using fields from foreign
   }

}

new ForeignWrapper(foreign)次に、標準の HashSet / HashMap に追加します。すべての状況に当てはまるわけではありませんが、おそらくあなたの状況には当てはまります。

于 2010-06-18T14:19:05.140 に答える
6

要素をソートしたくない/する必要がないようです。

その場合、代わりにHashMapandを使用できますか?ソートする必要がなければHashSet、使用する意味はSortedMapありません。SortedSet

于 2010-06-18T13:20:11.697 に答える
1

ソートされたものを保存したくありませんが、「通常の」マップとセットを使用すると、平等の動作を「オーバーライド」できませんでした。

要素を並べ替えて保存したくない場合は、なぜ並べ替えられたコレクションを使用しているのですか?

ソートされたコレクションを維持するために、挿入操作は(通常)O(log n)の複雑さを持ち、要素を正しい場所に配置します。並べ替えが必要ない場合は、O(1)の挿入時間を与えるハッシュベースのコレクション(HashMap、HashSet)を使用している可能性があるため、これは無駄です。

于 2010-06-18T13:21:57.980 に答える
1

SortedMapまたはSortedSetを同等に使用するアプローチは、(概念的には)同等のタイプではありませんか?

いいえ。これらのコレクションのポイントは、オブジェクトを並べ替えることができるようにすることです。オブジェクトに自然な並べ替え順序がない場合、並べ替えられたコレクションに入れることのポイントは何ですか。

equals()メソッドとhashcode()メソッドをオーバーライドし、代わりに標準のMap/Setクラスを使用する必要があります。

于 2010-06-18T13:22:06.233 に答える
1

hashCodeをオーバーライドする必要があるができない場合は、HashMapを拡張するか、独自に作成することを検討していると思います。

于 2010-06-18T13:24:35.580 に答える
1

メモリが大きな問題でない場合は、HashMap と HashSet をサブクラス化して Equality クラスを取得します

interface Equality<T>//Defines the equality behavior
{
   int hashCode(T t);//Required, always make sure equals = true => same hashCode
   boolean areEqual(T t,Object t2);
}
class EqualWrapper<T>//Wraps object and equality for the HashMap/Set
{
   T object;
   Equality<T> equal;
   int hashCode(){return equal.hashCode(object);}
   boolean equals(Object o){return equal.areEqual(object,o);}

}
class MySet<T>extends AbstractSet<T>
{
   private HashSet<EqualWrapper<T> > internalSet = new HashSet<T>();
   private Equality<T> equal;
   public MySet(Equality<T> et){equal = et;}
   // TODO implement abstract functions to wrapp 
   // objects and forward them to 
   // internalSet  
}

このようにして、独自の平等動作を定義できます。jreにな​​いのはおかしい

于 2010-06-18T14:29:59.020 に答える
1

明確ではありませんが、Set/Map の同じセマンティクスを使用して、somethingの Collection を取得しようとしているだけである可能性がありますが、 somethingは適切に実装されていませんObject.equals

AbstractSetその場合、orをサブクラス化AbstractMapし、オーバーライドAbstractCollection.containsして、equals のバージョンを使用することをお勧めします。

それは私がお勧めするものではありませんが、あなたの質問は、あなたが何を達成しようとしているのかを実際に明確にするものではありません.

http://java.sun.com/javase/6/docs/api/java/util/AbstractSet.html およびhttp://java.sun.com/javase/6/docs/api/java/util/AbstractCollectionを参照してください。 .html#contains(java.lang.Object)

于 2010-06-18T14:14:33.767 に答える
0

他の人が言っているように、自然な順序がない場合、SortedXXXは実際にはオプションではありません。ただし、要素を一覧表示するための何らかの一貫した方法が必要であると仮定して、同等性テストに使用しているフィールドを検討する場合、これらは「主キー」を構成し、ある種の数値またはアルファベット順を考え出します。あなたの目的に合うかもしれないそれらの周り。

于 2010-06-18T13:24:19.170 に答える
0

比較できないオブジェクトは並べ替えることができません。比較できない場合、2つのオブジェクトのどちらが最初に来るかをどのように知ることができますか?SortedMapしたがって、またはで比較できないオブジェクトを配置する方法はありませんSortedSet。(なぜあなたはしたいですか?別の種類のMapまたはを使用してくださいSet)。

equals()JavaのメソッドはクラスObjectで定義されており、すべてのクラスが拡張されObjectているため、すべてのオブジェクトにequals()メソッドがあります。equals()2つのオブジェクトが等しいかどうかを判断できるようにする場合は、クラスでオーバーライドして正しく実装するように注意する必要があります。

オブジェクトをハッシュベースのコレクション(HashMapまたはなどHashSet)に配置する場合は、オーバーライドする必要があり、それが正しい方法で実装されてhashCode()いることを確認する必要があります(その方法の詳細については、クラス内のこれらのメソッドのドキュメントを参照してください) 。hashCode()equals()Object

于 2010-06-18T13:18:21.557 に答える
0

作成時に Sorted[Set|Map] の実装に提供される (カスタム) Comparator を使用するだけです...

javadocs はこれを示唆する傾向があります:All keys inserted into a sorted map must implement the Comparable interface (or be accepted by the specified comparator).

SortedSet<MyObject> s = new TreeSet<MyObject>(new Comparator<MyObject>() {
    @Override
    public int compare(T o1, T o2) {
        // your very specific, fancy dancy code here
    }
});

http://java.sun.com/javase/6/docs/api/

于 2010-06-18T13:38:30.173 に答える
0

あなたの主張が正しいかどうかはわかりませんが(問題を間違った方向から解決しようとしていると思います)、挿入順序を維持するSetorが必要な場合は、それぞれorを使用してください。MapLinkedHashSetLinkedHashMap


更新:あなたの引用に従って:

外部クラスの平等動作を変更する必要があります。編集できません。

ソートされたセット/マップ内? 次に、カスタムで作成したTreeSetorを使用します。例えばTreeMapComparator

SortedSet<String> set = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);

String(大文字と小文字を区別しない順序で並べられた s のセットを構築します)。

以下も参照してください。

于 2010-06-18T13:38:59.010 に答える
0

並べ替えたものを保存したくありませんが、「通常の」マップとセットを使用すると、同等の動作を「オーバーライド」できませんでした。

不明なタイプの equals() メソッドをオーバーライドしようとしています。あなたは IEquatable インターフェースがあればいいのにという問題について考えています。SortedSet/SortedMap を使用する必要がある場合は、@ptomli の回答で言及されているような Comparator を提供します。

代わりに HashMap/HashSet を使用することをお勧めします。それらを見たことがありますか?

于 2010-06-18T13:49:25.200 に答える