Problema di HashSet: uguale e hashCode con contiene funzioni diverse da quelle che mi aspetto

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

Domanda

Ho il seguente codice:

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)

L'output è: 1 1 Ora con HashSet: 1 1 0

Tuttavia, mi sarei aspettato che anche l'ultima riga fosse vera (1). C'è qualcosa di ovvio che mi manca.

(sì, so che il mio metodo uguale e i metodi hashcode non tengono conto di alcuni problemi ... sono deliberatamente semplici, ma fatemi sapere se i problemi lì stanno causando questo problema)

È stato utile?

Soluzione

Non dovresti implementare gli uguali in stile Java e il metodo hashCode, ma gli equivalenti Python __eq__ e __hash__ . L'aggiunta di

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

aiuta. Questi metodi python sono - per quanto ne so - legati dinamicamente a hashCode ed equals () di Jython. Ciò garantisce che sia possibile inserire le classi Python nelle raccolte Java.

Ora il codice stampa cinque "1".

Altri suggerimenti

Ho scritto un codice equivalente in Java e produce true per tutte e tre le chiamate (). Quindi penso che questa debba essere una stranezza in Jython. Forse gli oggetti Java sottostanti non sono esattamente ciò che li vedi come in Python.

Non conosco Python, ma sembra che l'equivalente () e hashcode () dell'oggetto Java sottostante non stiano onorando il contratto richiesto.

  • Due oggetti se uguale a () deve restituire lo stesso hashcode ().

Sembra che sia stato violato. Gli Hashset utilizzeranno prima l'hashcode nella ricerca per ottenere l'elenco in cui si troverebbe l'oggetto corrispondente, quindi scorrere l'elenco per trovare quello uguale. Se il tuo hashcode non rispetta il contratto e stanno restituendo diversi hashcode, non lo troverà nell'hashset anche se fossero uguali () comparabili.

Il Java Object.hashcode () predefinito non restituirà lo stesso hashcode per 2 oggetti. Devi sostituirlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top