HashSet problema - iguais e hashCode com contém a trabalhar de forma diferente do que eu esperaria
-
04-07-2019 - |
Pergunta
Eu tenho o seguinte código:
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)
A saída é: 1 1 Agora com HashSet: 1 1 0
No entanto, eu teria esperado a última linha para ser verdade (1) também. Há algo óbvio que estou em falta.
(sim, eu sei que o meu método equals e hashCode métodos não levam algumas questões em consideração ... eles são deliberadamente simples, mas deixe-me saber se as questões não estão causando este problema)
Solução
Você não deve implementado o Java-Style iguais e método hashCode, mas em vez disso o Python equivaltents __eq__
e __hash__
. Adicionando
def __hash__(self):
return self.hashCode()
def __eq__(self, o):
return self.equals(o)
ajuda. Estes métodos Python são - tanto quanto eu sei - vinculados dinamicamente para hashCode e equals () por Jython. Isso garante que você pode colocar classes Python em coleções de Java.
Agora, os código imprime cinco "1".
Outras dicas
Eu escrevi código equivalente em Java e que não produz verdadeiro para todos os três contém chamadas (). Então eu acho que isso deve ser uma raridade em Jython. Talvez os objetos Java subjacentes não são exatamente o que você vê-los como em Python.
Eu não sei Python, mas com certeza parece iguais do objeto Java subjacente () e hashCode () não estão honrando o contrato necessário.
- dois objetos se equals () deve retornar o mesmo código hash ().
Parece que é violada. HashSets são primeiro vai usar o hashcode na pesquisa para obter a lista do objeto correspondente estaria em, em seguida, percorrer a lista para encontrar o que de igual. Se o seu código hash não está honrando o contrato e eles estão voltando diferentes hashcodes, então ele não vai encontrá-lo na hashset mesmo se fossem iguais () comparáveis.
O padrão Java Object.hashCode () não vai retornar o mesmo código hash para 2 objetos. Você tem que substituí-lo.