ハッシュセットの問題— equalsとhashCodeを含むhashCodeの動作が予想と異なる
-
04-07-2019 - |
質問
次のコードがあります:
class IncidentTag:
def __init__(self,tag):
self.tag = tag
def equals(self,obj):
return self.tag.equals(obj.tag)
def hashCode(self):
return self.tag.hashCode()
from java.lang import String
from java.util import HashMap
from java.util import HashSet
tag1 = IncidentTag(String("email"))
tag1copy = IncidentTag(String("email"))
tag2 = IncidentTag(String("notemail"))
print tag1.equals(tag1copy)
print tag2.equals(tag2)
print "Now with HashSet:"
hSet = HashSet()
hSet.add(tag1)
hSet.add(tag2)
print hSet.contains(tag1)
print hSet.contains(tag2)
print hSet.contains(tag1copy)
出力は次のとおりです。 1 1 HashSetで: 1 1 0
ただし、最後の行もtrue(1)になると予想していました。私が行方不明になっていることは明らかです。
(はい、私のequalsメソッドとhashcodeメソッドはいくつかの問題を考慮していないことを知っています...それらは意図的に単純ですが、問題がこの問題を引き起こしている場合はお知らせください)
解決
JavaスタイルのequalsおよびhashCodeメソッドを実装するのではなく、Pythonの同等の __ eq __
および __ hash __
を実装する必要があります。追加
def __hash__(self):
return self.hashCode()
def __eq__(self, o):
return self.equals(o)
ヘルプ。 これらのpythonメソッドは-私が知る限り-JythonによってhashCodeとequals()に動的にバインドされています。これにより、PythonクラスをJavaのコレクションに入れることができます。
コードは5つの「1」を出力します。
他のヒント
Javaで同等のコードを記述しましたが、3つのcontains()呼び出しすべてに対してtrueを生成します。だから、これはJythonでは奇妙なことだと思う。基礎となるJavaオブジェクトは、Pythonで見られるものとは正確に異なる可能性があります。
私はPythonを知りませんが、基礎となるJavaオブジェクトのequals()とhashcode()は必要な契約を守っていないようです。
- equals()が同じhashcode()を返す必要がある場合、2つのオブジェクト。
違反されているようです。 HashSetは最初にルックアップでハッシュコードを使用して、一致するオブジェクトが含まれるリストを取得し、次にリストを調べて等しいものを見つけます。ハッシュコードがコントラクトを尊重しておらず、異なるハッシュコードを返している場合、equals()が同等であっても、ハッシュセットでそれを見つけることはできません。
デフォルトのJava Object.hashcode()は、2つのオブジェクトに対して同じハッシュコードを返しません。オーバーライドする必要があります。