Java SortedSet+コンパレータの整合性、さらにはequals()の疑問
-
19-09-2019 - |
質問
思いSortedSetのコレクションを設定し、この場合、必ずというわけではないが、一般的に、なにより収集サイズです。このように違反するproscriptionのコンパレータとの整合性がequals()-すなわち、所蔵する不平等(異なる要素は比較的同じ値で、同じ数の要素).
Notionallyうものコンパレータ方法をソートセットが等しいサイズでの利用にかかることはありません本当に有+直感的に比較できるようこれらのコレクションは同サイズの少なくとも、私の特定の場合は、このように思われる。
この場合のように聞こえるかもしれないが問題なのか。
解決
ChssPly76コメントで書いたように、あなたは2つのコレクションが同じサイズを持っていますが、等しくない場合内のcompareToコールを決定するためにハッシュコードを使用することができます。これは、あなたが同じ大きさを持つ2つのコレクションを持っているまれな場合を除いて、正常に動作し、同じではありませんが、同じハッシュコードを持っています。確かに、その出来事の可能性はかなり小さいですが、それは考えられます。あなたは本当に慎重になりたい場合は、代わりのhashCodeの、代わりにSystem.identityHashCodeを使用しています。これはあなたのコレクションごとに固有の番号を与える必要があり、あなたが衝突を得るべきではありません。
一日の終わりには、これは、一致するサイズを持つ2つのコレクションの場合、任意の順序で、あなたのサイズによってソートセット内にコレクションを持つの機能を提供します。これはあなたが必要とするすべてである場合、それは通常の比較が可能であろうよりもはるかに遅いではありません。あなたが別のJVMインスタンス間の一貫性を保つために発注する必要がある場合、これは動作しません、あなたはそれにいくつかの他の方法を行う必要があるでしょう。
擬似コード:
if (a.equals(b)) {
return 0;
} else if (a.size() > b.size()) {
return 1;
} else if (b.size() > a.size()) {
return -1;
} else {
return System.identityHashCode(a) > System.identityHashCode(b) ? 1 : -1;
}
他のヒント
SortedSet
インタフェースコア Set
これに従うべきである契約の概要 Set
仕様となります。
る唯一のためて要素の equal()
方法行動をとお Comparator
-付加価値をつけられるというのはその中核 Set
の運営等に対し SortedSet
を行います。
例えば、 add()
法定義されたコアセットインタフェースを指定することができない要素を追加の設定がすでに要素が equal()
方法がtrueを返すこの新たな要素としての引数。も SortedSet
使用していない equal()
, を用い compareTo()
.シンプルな compareTo()
を返します false
ご要素に追加された場合でも equals()
入り口を分かりやすくした方が true
, この Set
契約になります。
はなこ 実践的な 問題そのものにしています。 SortedSet
行動は常に一貫した場合でも、 compare()
vs equals()
んでいます。
このは禁止に違反しているようです コンパレータは、一貫して持っています すなわち、2つのコレクション - 等号()と 異なる有すること(不均等であってもよいです 要素)が、同じと比較 値(彼らは同じを持っているので、 要素の数)。
は要求されないが、いずれかComparator
はboolean equals(Object)
のオブジェクトの実装と一致すること、(Javadocの)記載または暗示。
そのComparable
とComparator
注異なる目的で異なるインターフェースのです。 Comparable
はクラスの「自然」の順序を定義するために使用されます。その意味で、それはequals
と一致しないことにするcompateTo
に悪い考えです。あなたはクラスの自然な順序とは異なる順序を使用する場合これとは対照的に、Comparator
が使用されます。
編集:ここにSortedSetのJavadocからの完全な段落があります。
なおによって維持発注 ソートセット(明示的かどうか コンパレータが提供される)でなければなりません equalsと一貫性の並べ替えた場合 セットが正しく設定を実装することです インタフェース。 (Comparableを参照 以下のためのインタフェースやコンパレータインタフェース 一貫の正確な定義 イコールで。)これはとてもためであります 設定インターフェイスはで定義されます 操作に等しいが、ソート セットには、すべての要素の比較を行い、 そののcompareToを使用して(または比較) ある方法ので、2つの要素 から、この方法によって等しいとみなさ ソートセットの観点、 等しい。 のソートセットの動作です その順序であっても、明確に定義されました equalsと矛盾します。それだけ の一般規約に従っていません Setインタフェース。の
私は最後の文を強調しています。ポイントは、あなたが最も可能性の高い期待などにSortedSetは動作しますが、いくつかの操作の動作が正確にSet
仕様と一致しません...仕様はequals
方法の面で彼らの行動を定義するためということです。
実際には、がそう一貫性のためのの規定の要件(私のミス)であるが、それを無視しての結果は、あなたが想像するほど悪くはありません。もちろん、それはあなたがそれを行うべきかどうかを決定する次第です。私の推定では、それはOKである必要があり、あなたが徹底的にコードをコメントしたSortedSetが「リーク」しないことを確認していることを提供します。
しかし、それだけのコレクション「サイズ」を見て、コレクションのためのコンパレータは、セマンティックな観点から...仕事しようとしていることを私に明確ではありません。私が意味する、あなたは本当に(例えば)2つの要素を持つすべてのコレクションが等しいことを言いたいのですか?これはあなたのセットでのみ、これまで任意のサイズの一つのコレクションを含めることができることを意味します...
Comparator
がequals()
と同じ結果を返す必要がない理由はありません。 Comparator
だけでは十分ではありませんので、実際には、equals()
のAPIが導入されました:あなたは、コレクションをソートしたい場合は、次の2つの要素が小さいか大きいかどうかを知る必要があります。
これは、にSortedSetは、標準APIの一部として、Setインタフェースで定義された契約を破り、代わりにequalsメソッドの平等を定義するためにコンパレータを使用していますが、それはそれがどのようにだと少し奇妙だ。
あなたの実際の問題はcontaintedコレクションのサイズに応じて、コレクションのコレクションをソートする場合には、あなたはCollections.sort(リスト、コンパレータ>)を使用してソートすることができますリスト、との優れている;