3

私は間違っているかもしれませんが、私にとっては、オブジェクトのequalsをオーバーライドして、意味のあるequalsであるとみなすことができます。マップ内のすべてのエントリには個別のキーがあり、セット内のすべてのエントリには個別の値があります(意味のある等しいものではありません)

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

ソートされたコレクションを使用して、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());
}

new String( "xxx")を使用すると、文字列プールの使用がバイパスされるため、s1!=s2になることに注意してください。セットサイズが1ではなく2になるようにコンパレータを実装する方法を知りたいのですが。

主な質問は次のとおりです。同じ文字列値の2つの異なるインスタンスの場合、コンパレータで!= 0を返すにはどうすればよいですか?

そのコンパレータにルールを尊重させたいことに注意してください。

順序について2つの引数を比較します。最初の引数が2番目の引数よりも小さい、等しい、または大きい場合、負の整数、ゼロ、または正の整数を返します。実装者は、すべてのxとyに対してsgn(compare(x、y))== -sgn(compare(y、x))であることを確認する必要があります。(これは、compare(y、x)が例外をスローする場合にのみ、compare(x、y)が例外をスローする必要があることを意味します。)

実装者は、関係が推移的であることも確認する必要があります:((compare(x、y)> 0)&&(compare(y、z)> 0))はcompare(x、z)>0を意味します。

最後に、実装者は、compare(x、y)== 0がすべてのzに対してsgn(compare(x、z))== sgn(compare(y、z))を意味することを確認する必要があります。

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

私は次のようなトリックを使うことができます:

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

正常に動作しているように見えますが、compare(s1、s2)!= -compare(s2、s1)であるため、ルールは尊重されません。

それで、この問題に対するエレガントな解決策はありますか?


編集:なぜ私がそのようなことを尋ねるのか疑問に思っている人のために。それは、現実の問題よりも好奇心によるものです。

しかし、私はすでにそのような状況にあり、この問題の解決策についてですが:

あなたが持っていると想像してください:

class Label {
  String label;
}

ラベルごとに、関連付けられた文字列値があります。マップ、label->valueが必要な場合はどうでしょうか。しかし、マップキーと同じラベルを2倍持つことができるようにするにはどうすればよいでしょうか。Ex "label"(ref1)-> value1 "label"(ref2)-> value22つの異なるLabelインスタンスが等しくないようにequalsを実装できます->HashMapで機能すると思います。

しかし、これらのLabelオブジェクトをアルファベット順に並べ替えることができるようにするにはどうすればよいでしょうか。コンパレータを提供するか、同等のものを実装する必要があります。しかし、同じラベルを持つ2つのラベルをどのように区別することができますか?我々はしなければならない!compare(ref1、ref2)は0を返すことはできません。ただし、-1または1を返す必要がありますか?メモリアドレスなどを比較してそのような決定を下すことができますが、Javaでは不可能だと思います...

4

6 に答える 6

6

Guavaを使用している場合はOrdering.arbitrary()、を使用できます。これにより、VMの存続期間中、一貫性を維持する要素に追加の順序が課されます。これを使用して、コンパレータの関係を一貫した方法で解除できます。

ただし、間違ったデータ構造を使用している可能性があります。複数のインスタンスを追加できるMultiset(など)の使用を検討しましたか?TreeMultiset

于 2012-04-25T12:46:44.117 に答える
3

Try using the following Comparator (for your example):

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

これにより、自然な比較可能な順序に従って物事が並べ替えられますが、自然な順序が等しい場合は、任意の順序にフォールバックして、個別のオブジェクトが個別のままになります。

于 2012-04-25T18:26:21.913 に答える
2

それをするのが良い考えかどうかはわかりません。のjavadocからComparator

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

于 2012-04-25T12:48:34.770 に答える
0

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

于 2012-04-25T12:51:43.277 に答える
0

You might want to use a SortedSet<Collection<String>> or similar, since - as you mentioned - a sorted doesn't allow you to add multiple equal entries.

Altenatively you can use Guava's MultiSet.

From the JavaDoc on SortedSet:

Note that the ordering maintained by a sorted set (whether or not an explicit comparator is provided) must be consistent with equals if the sorted set is to correctly implement the Set interface.

However, one question still remains: why do you want to have two distinct instances that are logically equal (that's what equals() actually means).

于 2012-04-25T12:55:11.857 に答える
-2

The comparator should actualy return 0 only when the two references refer to the same object, like this:

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;
   } 
}
于 2012-04-25T12:54:37.363 に答える