2012-04-25 10 views
3

私は間違っているかもしれませんが、私にとっては、オブジェクトの等価をオーバーライドして、それらが有意義に等しいとみなせるようにすることができます。 マップ内のすべてのエントリに異なるキーがあり、セット内のすべてのエントリに異なる値があります(有意義ではありません)Sortedコレクション内の2つの等しいオブジェクトを区別するにはどうすればよいですか?

しかし、TreeMapまたはTreeSetを使用するとコンパレータを提供できます。 コンパレータが用意されていると、オブジェクトのequalsメソッドがバイパスされ、コンパレータが0を返すときに2つのオブジェクトが等しいとみなされることに気づきました。 したがって、2つのオブジェクトがありますが、マップキーセット、保持された。

ソートされたコレクションを使用して、2つの異なるインスタンスを区別することが可能かどうかを知りたいと思います。

ここでは簡単のサンプルです:!

public static void main(String[] args) { 
    TreeSet<String> set = new TreeSet<String>(); 
    String s1 = new String("toto"); 
    String s2 = new String("toto"); 
    System.out.println(s1 == s2); 
    set.add(s1); 
    set.add(s2); 
    System.out.println(set.size()); 
} 

( "XXX")を新しい文字列を使用して文字列プールの使用を回避することに注意してください、これS1 = s2が。 コンパイラを実装する方法を知りたいので、サイズが2ではなく1になるようにしてください。

主な質問は、同じ文字列値の2つの異なるインスタンスについてです。私の比較で?私はそのコンパレータがルールを尊重したいのですが

注:

はオーダーのために2つの引数を比較します。最初の引数が2番目の引数よりも小さい、等しい、または大きい場合は、負の整数、ゼロまたは正の整数を返します。実装者は、すべてのxとyについてsgn(compare(x、y))== -sgn(compare(y、x))を保証する必要があります。

実装者は、関係が推移的であることを確実にする必要があります。((compare(x、y))は、例外をスローする必要があります。 (y、z)> 0))は、compare(x、z)> 0を意味する。

最後に、compare(x、y)== 0は、すべてのzに対してsgn(compare(x、z))== sgn(y(z))を保証する必要があります。

(compare(x、y)== 0)==(x.equals(y))が一般的ですが、必ずしもそうである必要はありません。一般に、この条件に違反するコンパレータは、この事実を明確に示すはずです。推奨される言語は "注:このコンパレータはequalsと矛盾する順序を課します。"

私のようなトリックを使用することができます!

public int compare(String s1,String s2) { 
    if s1.equals(s2) { return -1 } 
    ... 
} 

= -compare(S2、S1)正常に動作するようですが、(S1、S2)を比較するため、ルールは尊重されていません

この問題の解決策はありますか?


編集:私はそのようなことを聞​​いて、なぜ疑問に思ったもののために。実際の人生の問題よりも好奇心である。

しかし、私はすでにそのような状況にしてきたし、この問題の程度解決かかわら:

はあなたが持っている想像:

class Label { 
    String label; 
} 

各ラベルのためにあなたが関連付けられた文字列値を持っています。 ここで、label-> valueのマップを作成する場合はどうなりますか? しかし、マップキーと同じラベルを2回使用できるようにしたい場合はどうなりますか? Ex "label"(ref1) - > value1 "label"(ref2) - > value2 equalsを実装すると、2つの異なるLabelインスタンスが等しくないようになります。>これはHashMapで動作すると思います。

しかし、これらのラベルオブジェクトをアルファベット順にソートできるようにしたいのですが? コンパレータを提供するか、同等の機能を実装する必要があります。 しかし、同じラベルを持つ2つのラベルの間で注文を区別することはできますか? 私たちはする必要があります! compare(ref1、ref2)は0を返してはいけません。しかし、それは-1か1を返しますか?あなたはグアバを使用している場合 追加を課すであろう、あなたはOrdering.arbitrary()を利用することができ、...

+0

私は実際の識別子ではないので、Stringsをあなたのケースでは識別子(マップ用のキー)として使用しないでください。もしあなたが文字列 '' label ''を持っていれば、どのように2つの' 'Label''オブジェクトのどちらを知りたいでしょうか? – adranale

+0

これはちょうど例ですが、実際には私は "ラベル"を持っているわけではありませんが、参照を分けなければなりません –

答えて

6

を私たちは、このような決定を行うためにそのようなメモリアドレスか何かを比較することができますが、私はそれがJavaで可能ではないと思います要素の順序は、VMの寿命に一貫性があります。これを使用して、Comparator内のタイを一貫性のある方法で破ります。

ただし、誤ったデータ構造を使用している可能性があります。 Multiset(例:TreeMultiset)を使用すると考えましたか?複数のインスタンスを追加できますか?

+0

この縫い目は面白いですね、実際に注文を出すためには、 1または+1)が2つの等号の間に!=文字列ですか? –

+2

かなり面白いです。 System.identityHashCode()を最初のパスとして使用し、衝突が発生した場合は、新しいインスタンスごとにUIDのリストを保持します。 http://guava-libraries.googlecode.com/svn-history/r311/trunk/javadoc/src-html/com/google/common/collect/Ordering.html –

+0

非常に面白いです。私はすでにハッシュコードを使用して区別をしています(返されたhash1 - hash2)が、(予想外の)衝突のために満足しませんでした。 –

2

私はそれを行うことをお勧めします。 ComparatorのJavadocから: (またはソートマップ)を設定ソートを注文するequalsと一貫性のない順序付けを課す できるコンパレータを使用した場合

注意を払うべきです。明示的な コンパレータcを持つソートされた集合(またはソートされたマップ)が、集合Sから引き出された要素(またはキー)で使用されているとします。 Sのcによって課せられた順序がequalsと矛盾する場合、ソートされた 集合マップ)は「不思議なことに」動作します。特にソートされた セット(またはソートされたマップ)は、set(または マップ)の一般契約に違反します。これは、equalsで定義されています。

+0

私はあなたが何を意味しているのかを理解し、起こりうる危険な行動を見ています(例えば、key1でマップし、key2でkey1のエントリを取得していますが、!key1.equals(k2))。私の例では問題になるかもしれませんが、私は2つの異なるインスタンスを区別するequalsメソッドを持つことができます。 –

0

等しいオブジェクトでソートされたコレクションが必要な場合は、すべてのオブジェクトをリストに入れてCollections.sort()を使用できます。

+0

地図はどうですか? –

+0

@SebastienLorber - 複数の等しいキーが含まれている場合、どのようにマップから何かを取得しますか? – jtahlborn

+0

基本的には、異なるインスタンスのためにキーが等しくない(文字列との私の例は、その文字列を編集できないためおそらく適切ではない) –

-2

2つの参照がこのように、同じオブジェクトを参照する場合にのみactualy 0を返す必要がコンパレータ:

public int compare(String s1,String s2) { 
    if (s1!=s2) { 
     int result = s1.compareTo(s2); 
     if (result == 0) { 
      return -1; 
     } else { 
      return result; 
     } 
    } else { 
     return 0; 
    } 
} 
+0

compare(s1、s2)= -compare(s2、s1) ) そこ。 –

+0

私は答えを編集しました – adranale

+0

まだ比較はありません(s1、s2)= -compare(s2、s1) –

0

あなたは以来SortedSet<Collection<String>>または類似し、使用することをお勧めします - あなたが言及したように - ソートのdoesn複数の等しい項目を追加することはできません。

また、GuavaのMultiSetを使用することもできます。SortedSetに対してjavadocから

:ソートセットが正しく実装するのであればソートセットによって維持順序が(明示的なコンパレータが提供されているかどうか)イコールと一致していなければならないということ

注意Setインタフェース

しかし、なぜ論理的に等しい2つの別個のインスタンス(これは実際には、equals()が意味することです)が必要ですか。

3

は(あなたの例のために)、以下のコンパレータを使用してみてください:

Comparator<String> comp = Ordering.natural().compound(Ordering.arbitrary()); 

これは、彼らの自然匹敵する順序に従って物事をソートしますが、自然な順序が等しいときように、それは任意の順序にフォールバックします明確なオブジェクトは別個のままです。

+0

ありがとう、私はそのグアバ任意のメソッドが必要です。しかし、あなたはそのような機能の使用を明白にしているので+1 –

関連する問題