ハッシュセットの問題— equalsとhashCodeを含むhashCodeの動作が予想と異なる

StackOverflow https://stackoverflow.com/questions/230585

質問

次のコードがあります:

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つのオブジェクトに対して同じハッシュコードを返しません。オーバーライドする必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top