Object
Java にはメソッドがありますが、や などhashCode
の連想コンテナーでのみ使用されています。なぜそのように設計されたのですか?メソッドを持つインターフェイスは、はるかにエレガントなソリューションのように見えます。HashSet
HashMap
Hashable
hashCode
2 に答える
主な議論は、hashCode
Javaオブジェクトに対して計算できる明確に定義されたデフォルトがあり、同様に明確に定義されているequals
. すべてのオブジェクトからこの関数を差し控える正当な理由はありません。もちろん、差し控えない理由はたくさんあります。だから、それは私の本では簡単です。
Comparator
この質問は、 (とは異なるComparable
)のように動作するがハッシュ用のインターフェイスがない理由を尋ねる別の質問と重複していると主張されています。.NET には と呼ばれるそのようなインターフェイスが含まれており、IEqualityComparer
Java にも同様のことができるように思われます。現状では、大文字と小文字を区別しない方法 (おそらく の最も一般的な使用方法) で文字列を他のオブジェクトにマップするなどの Java コレクションが必要な場合は、大文字と小文字を区別しないメソッドとIEqualityComparer
オブジェクトで文字列をラップする必要があります。.hashCode
equals
大きな問題は、「equalityComparer」インターフェースは便利かもしれませんが、多くの場合、等価関係を効率的にテストするには情報のキャッシュが必要になることだと思います。たとえば、大文字と小文字を区別しない文字列ハッシュ関数は、渡された文字列の大文字のみのコピーを作成してそれを呼び出すhashCode
ことができますが、特定の文字列のハッシュコードに対するすべての要求で、への変換が繰り返されることを回避することは困難です。大文字とその大文字値のハッシュ。対照的に、「大文字と小文字を区別しない文字列」オブジェクトには、文字列の大文字のみのコピーのフィールドを含めることができます。これは、インスタンスに対して 1 回だけ生成する必要があります。
は、生の文字列を大文字のみの文字列に変換する のようなものを含んでいれば、妥当なパフォーマンスを達成できますが、そのような設計では、外部から見える状態がないにもかかわらず、異なるインスタンスを使用するために異なるスレッドが必要になるか、パフォーマンスEqualityComparer
を奪うロックとロックが必要になります。シングルスレッドのシナリオでも同期コード。WeakHashMap<string,string>
EqualityComparer
ちなみに、コンパレータ スタイルのインターフェイスで発生する 2 つ目の問題は、外部から提供されたコンパレータを使用するコレクション型 (ランクまたは同等性を比較するかどうか) は、コンパレータ自体がそれを使用するクラスの状態の一部になることです。ハッシュ テーブルが異なる EqualityComparer インスタンスを使用している場合、2 つのコンパレータがすべての状況で同じように動作する場合でも、それらが安全に同等であると見なされるかどうかを知る方法がない場合があります。