2013-08-22 11 views
6

Ho trovato questo commento su can StringBuffer objects be keys in TreeSet in Java?Ho bisogno di un metodo di equals e Hashcode se la mia classe implementa comparabili in Java?

"Ci sono 2 strategie identificativi utilizzati con mappe delle città in Java (più o meno)

hashing:. Un ingresso 'Pippo' è convertito in un best-come- possibile tentativo di generare un numero che accede in modo univoco a un indice in un array. (Puristi, per favore non abusare di me, sto intenzionalmente semplificando) .Questo indice è dove il tuo valore è memorizzato. C'è la possibilità probabile che "Foo" e "Bar" in realtà genera lo stesso valore di indice, il che significa che sarebbero entrambi mappati sulla stessa posizione dell'array. Ovviamente questo non funziona e quindi è qui che entra in gioco il metodo "equals()", usato per disambiguare

Confronto: utilizzando un metodo comparativo non è necessario questo passaggio di disambiguazione in più perché il confronto MAI produce questa collisione in primo luogo. L'unica chiave che "Foo" è uguale a "Foo". Una buona idea è se è possibile definire "equals()" come compareTo() == 0; per coerenza. . Non è un requisito"

la mia domanda è la seguente: se la mia classe implementa paragonabile, allora cosa significa non devo sovrascrivere equals e metodo di codice hash per l'utilizzo di miei oggetti come chiavi in ​​collezioni Hash per esempio

class Person implements Comparable<Person> { 
    int id; 
    String name; 

    public Person(int id, String name) { 
     this.id=id; 
     this.name=name; 
    } 

    public int compareTo(Person other) { 
     return this.id-other.id; 
    } 
} 
.

Ora, posso usare i miei oggetti Person in collezioni hashable?

+0

Hai provato? –

risposta

6

L'articolo che Brough sta parlando TreeSet. un insieme albero è un albero con ogni nodo ha un posto definito dal suo valore in confronto agli altri valori già nell'albero

a hashTable memorizza coppie chiave/valore in una tabella hash. Quando si utilizza una Hashtable, si specifica un oggetto che viene utilizzato come chiave e il valore che si desidera collegare a quella chiave. La chiave viene quindi sottoposta a hash e il codice hash risultante viene utilizzato come indice al quale il valore viene archiviato nella tabella.

la differenza tra Hashable e TreeSet è che il set di alberi non ha bisogno di hashCode, è solo necessario sapere se è necessario prendere l'elemento a sinistra o destra nell'albero. per quello puoi usare Compare e niente di più.

in hashTable un confronto è sufficiente, perché è costruito in modo diverso, ogni oggetto arriva alla sua cella eseguendo l'hashing, non confrontandolo con gli elementi già presenti nella raccolta.

quindi la risposta è no, è possibile 'utilizzare Person in hashtable solo con compareTo. u deve ignorare hashCode() e equals() per questo

vi suggerisco anche di leggere this articolo su hashtables

1

se la mia classe implementa paragonabile, allora vuol dire non devo sovrascrivere equals e metodo di codice hash per l'utilizzo di miei oggetti come chiavi nelle raccolte di hash. es.

No, è ancora necessario implementare equals() e hashCode(). I metodi svolgono funzioni molto diverse e non possono essere sostituiti da compareTo().

  • equals() restituisce un valore booleano basato sull'uguaglianza dell'oggetto. Di solito è l'equità identità e non l'uguaglianza di campo. Questo può essere molto diverso dai campi utilizzati per confrontare un oggetto in compareTo(...) anche se ha un senso per l'entità, il metodo equals() può essere:

    @Overrides 
    public boolean equals(Object obj) { 
        if (obj == null || obj.getClass() != getClass()) { 
         return false; 
        } else { 
         return compareTo((Person)obj) == 0; 
        } 
    } 
    
  • hashCode() restituisce un valore intero per l'istanza che viene utilizzato in tabelle hash per calcolare il bucket in cui deve essere inserito. Non esiste un modo equivalente per ottenere questo valore da compareTo(...).

+0

Ho quasi invalutato la tua risposta, ma io sono del tipo "usa' instanceof' per la scuola 'equals'". –

+0

LOL! In realtà lo sono anche io, ma ero in modalità velocità e volevo che il codice fosse generico in tutte le classi. :-) @ ChrisJester-Young. – Gray

+1

quando si restituisce 'compareTo ((Person) obj)' si restituisce un 'int', ma equivale a aspettarsi il tipo di ritorno' boolean', corretto? – eagertoLearn

2

HashTable utilizza equals e hashCode. Ogni classe ha quei metodi. Se non li realizzi, li erediti.

Se è necessario implementarli dipende dal fatto che la versione ereditata sia adatta ai propri scopi. In particolare, poiché Person non ha una superclasse specifica, eredita i metodi Object. Ciò significa che un oggetto Persona è uguale solo a se stesso.

Avete bisogno di due oggetti Persona distinti da considerare uguali ai tasti di HashTable?

0

TreeSet ha bisogno di Paragonabile, per aggiungere valori a destra o a sinistra dell'albero. HashMap richiede i metodi equals() e Hashcode() che sono disponibili dalla classe Object ma devi sovrascriverli per il tuo scopo.

0

Se una classe implementa Comparable, ciò suggerisce che le istanze della classe rappresentano valori di qualche tipo; generalmente, quando le classi incapsulano i valori sarà possibile che esistano due istanze distinte che mantengono lo stesso valore e dovrebbero quindi essere considerate equivalenti. Quanto l'unico modo per istanze di oggetti distinti da considerare equivalente è per loro sostituiscono equals e hashCode, che implica che le cose che implementano Comparable dovrebbero sostituire equals e hashCodea meno i valori incapsulati su cui compare opera sarà globalmente univoco (implicando tali istanze distinte non dovrebbero mai essere considerate equivalenti).

Come esempio semplice, si supponga che una classe includa un campo di tipo long; ogni volta che viene creata un'istanza, tale membro viene impostato su un valore recuperato da un singleton AtomicLong e Comparable utilizza tale campo per classificare gli oggetti nell'ordine di creazione. Due istanze distinte della classe non riporteranno mai lo stesso CreationRank; di conseguenza, l'unico modo in cui x.equals(y) dovrebbe mai essere vero è se x e si riferiscono alla stessa istanza dell'oggetto - esattamente come funzionano le impostazioni predefinite equals e hashCode.

proposito, avendo x.compare(y) ritorno a zero dovrebbe generalmente implica che x.equals(y) tornerà vero, e viceversa, ma ci sono alcuni casi in cui x.equals(y) può essere falsa ma x.compare(y) dovrebbe comunque restituire zero. Questo può essere il caso in cui un oggetto incapsula alcune proprietà che possono essere classificate e altre che non possono. Si consideri, ad esempio, un tipo ipotetico FutureAction che incapsula un DateTime e un'implementazione di un'interfaccia DoSomething.Tali cose potrebbero essere classificate in base alla data e all'ora incapsulate, ma potrebbe non esserci alcun modo ragionevole per classificare due elementi che hanno la stessa data e ora, ma azioni diverse. Avere il rapporto equals false mentre i report compare zero avrebbe più senso che fingere che gli elementi chiaramente non equivalenti dovrebbero essere chiamati "uguali".

Problemi correlati