HashSet problema - iguais e hashCode com contém a trabalhar de forma diferente do que eu esperaria

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

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)

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top