2010-06-02 13 views
8

Ho una classe, "Accumulatore", che implementa il metodo Comparable Comparable, e sto cercando di mettere questi oggetti in un HashSet.Java HashSet consente i duplicati; problema con paragonabile?

Quando aggiungo() a HashSet, non vedo alcuna attività nel mio metodo compareTo nel debugger, indipendentemente da dove ho impostato i miei punti di interruzione. Inoltre, quando ho finito con l'add() s, vedo diversi duplicati all'interno del Set.

Che cosa sto rovinando, qui; perché non sta comparando, e quindi, permettendo i dupes?

Grazie,
IVR Avenger

risposta

15

Che cosa sto rovinando, qui?

HashSet si basa su hashCode(), non su compareTo(). Potresti confonderlo con TreeSet. In entrambi i casi, assicurarsi di implementare anche equals() in un modo coerente con l'altro metodo.

10

è necessario implementare correttamente hashCode() e equals().

È necessario eseguire l'override di hashCode e restituire un numero in base ai valori della classe in modo tale che due oggetti uguali abbiano lo stesso codice hash.

+0

senza eguali sarebbe completamente invalido. – Justin

1

HashSet utilizza hashCode ed è uguale a. TreeSet utilizza l'interfaccia Comparable. Nota: se decidi di sovrascrivere hashcode o uguale, devi sempre sostituire l'altro.

+1

Hai solo bisogno di sovrascrivere hashCode se uguali è sovrascritto (la definizione è l'uguaglianza è cambiata). L'altro modo non è necessariamente vero. È perfettamente legale cambiare hashCode per restituire 1 e lasciare solo gli uguali. –

2

Quando hashCode restituisce valori diversi per 2 oggetti, non viene utilizzato uguale. Btw, compareTo non ha nulla a che fare con hashing collezioni :) ma raccolta differenziata

2

I suoi oggetti sono Comparable, e probabilmente hai implementato equals() troppo, ma HashSets accordo con hash degli oggetti, e le probabilità sono che non avete implementato hashCode() (o l'implementazione di hashCode() non restituisce lo stesso hash per due oggetti che sono (a.equals(b) == true).

4

HashSet utilizza i hashCode() e equals() metodi per evitare i duplicati vengano aggiunti. in primo luogo, si ottiene il codice hash dell'oggetto che si desidera Poi, trova il corrispondente secchio per t hat hash code e itera su ogni oggetto in quel bucket, usando il metodo equals() per vedere se esistono già oggetti identici nel set.

Il debugger non si rompe su compareTo() perché non viene mai utilizzato con HashSet!

Le regole sono:

  1. se due oggetti sono uguali, allora i loro codici hash devono essere uguali.

  2. Ma se i codici di hash due degli oggetti sono uguali, allora questo non vuol dire gli oggetti sono uguali!Potrebbe essere che i due oggetti abbiano lo stesso hash.

1

Quando mai si crea un oggetto della classe Accumulator ci vuole un nuovo spazio in JVM e restituisce unica hashCode ogni volta che si aggiunge un oggetto in hashset. Essa non dipende dal valore dell'oggetto perché non avete sovrascritto il metodo hashCode() quindi chiamerà oggetto classe hashCode() metodo che restituirà hashCode unico, con ogni oggetto creato nel programma.

Soluzione:

Override hashCode() e equals() metodo e applicare la logica a seconda delle proprietà della vostra classe. Assicurarsi di leggere eguali e contratto hashcode

http://www.ibm.com/developerworks/java/library/j-jtp05273/index.html

+0

il link fornito è molto utile e per le persone bininome come me è molto utile. –

2

Una cosa che la gente tende a ignorare che si traducono in un enorme errore. Durante la definizione del metodo equals, prendere sempre il parametro come classe dell'oggetto e quindi convertire l'oggetto nella classe desiderata. Per esempio

public bolean equals(Object aSong){ 
    if(!(aSoneg instanceof Song)){ 
     return false; 
    } 
    Song s=(Song) aSong; 
    return getTitle().equals(s.getTitle()); 
    } 

Se u passano scrivere Canzone aSong invece di Object aSong metodo tuoi pari non otterrà mai chiamato.

Spero che questo aiuti