Problema de HashSet & # 8212; equals y hashCode con contiene funciona de manera diferente de lo que esperaba

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

Pregunta

Tengo el siguiente 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)

La salida es: 1 1 Ahora con HashSet: 1 1 0

Sin embargo, también hubiera esperado que la última línea fuera verdadera (1). ¿Hay algo obvio que me estoy perdiendo?

(sí, sé que mis métodos de método equitativo y de código de hash no tienen en cuenta algunos problemas ... son deliberadamente simples, pero sí me avisan si los problemas que están causando este problema)

¿Fue útil?

Solución

No debe implementar los métodos de estilo de código y hashCode de Java, sino los equivalentes de Python __eq__ y __hash__ . Añadiendo

def __hash__(self):
    return self.hashCode()
def __eq__(self, o):
    return self.equals(o)

ayuda. Estos métodos de Python están, hasta donde yo sé, unidos dinámicamente a hashCode y equals () por Jython. Esto garantiza que pueda colocar clases de Python en las colecciones de Java.

Ahora el código imprime cinco " 1 " ;.

Otros consejos

Escribí código equivalente en Java y produce verdadero para las tres llamadas contiene (). Así que creo que esto debe ser una rareza en Jython. Tal vez los objetos Java subyacentes no son exactamente como los ve en Python.

No conozco Python, pero parece que los objetos subyacentes equals () y hashcode () no están cumpliendo el contrato requerido.

  • Dos objetos si equals () deben devolver el mismo código hash ().

Parece que se viola eso. Los HashSets primero usarán el hashcode en la búsqueda para obtener la lista en la que estaría el objeto coincidente, luego revisen la lista para encontrar el que sea igual. Si su código hash no está cumpliendo el contrato y están devolviendo diferentes códigos hash, entonces no lo encontrará en el hashset incluso si fueran iguales () comparables.

El Java Object.hashcode () predeterminado no devolverá el mismo código hash para 2 objetos. Tienes que anularlo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top