2016-04-23 15 views
9

Ho la seguente classe:HashSet aggiunge voci duplicate nonostante attuazione sia hashCode() e equals()

class Point 
{ 
    double x, y; 

    // .... constructor and other functions here 

    public boolean equals(Point p) 
    { 
     if(p==null) return(false); 
     return(x==p.x && y==p.y); 
    } 

    public int hashCode() 
    { 
     int result=17; 

     long c1=Double.doubleToLongBits(x); 
     long c2=Double.doubleToLongBits(y); 

     int ci1=(int)(c1^(c1 >>> 32)); 
     int ci2=(int)(c2^(c2 >>> 32)); 

     result = 31 * result + ci1; 
     result = 31 * result + ci2; 

     return result; 
    } 
} 

Ora, se scrivo il seguente codice:

Point x=new Point(11,7); 
    Point y=new Point(11,7); 

    System.out.println("hash-code of x=" + x.hashCode()); 
    System.out.println("hash-code of y=" + y.hashCode()); 
    System.out.println("x.equals(y) = " + x.equals(y)); 
    System.out.println("x==y = " + (x==y)); 

    java.util.HashSet<Point> s=new java.util.HashSet<Point>(); 
    s.add(x); 
    System.out.println("Contains "+y.toString()+" = "+s.contains(y)); 
    s.add(y); 
    System.out.println("Set size: "+s.size()); 
    java.util.Iterator<Point> itr=s.iterator(); 
    while(itr.hasNext()) System.out.println(itr.next().toString()); 

Sto ottenendo il output seguente:

hash-code of x=79052753 
hash-code of y=79052753 
x.equals(y) = true 
x==y = false 
Contains (11.0,7.0) = false 
Set size: 2 
(11.0,7.0) 
(11.0,7.0) 

Ti prego, aiutami a capire perché contiene() restituisce false (anche dopo equals() e hashCode() restituisce lo stesso valore) e come posso rettificare questo (es. impedendo a Java di aggiungere elementi duplicati). Grazie in anticipo.

+2

Wow! Sarebbe fantastico se tutte le domande fossero così chiare e comprensibili e avessero codice e output da riprodurre. Molto bene! – Seelenvirtuose

risposta

7

Non si sta eseguendo l'override del metodo di uguale in Oggetto.

La firma di metodo equals è:

public boolean equals(Object obj) 

e non

public boolean equals(Point obj) 

E per favore non confrontare i valori doppi utilizzando ==. Dovresti invece utilizzare Double.equals.

+1

Il valore dei tipi semplici può essere confrontato usando == –

+2

@SergeyMorozov - No. L'utilizzo di == per i confronti a virgola mobile non è raccomandato. Non è sicuro. – Madhusudhan

+0

Grazie, ha risolto il mio problema. Per quanto riguarda il confronto, secondo la documentazione, Double.equals restituisce false quando vengono confrontati -0.0 e +0.0; quindi penso che vorrei attenermi a == di Double.equals(). – user1637645

6

La firma del metodo è stata cambiata da Object.equals(Object), pertanto non si sta sovrascrivendo correttamente equals. Ti suggerisco di usare l'annotazione @Override per catturare questa classe di bug. Il tuo metodo dovrebbe assomigliare a:

@Override 
public boolean equals(Object o) 
{ 
    if (this == o) { 
     return true; 
    } 
    if (o instanceof Point) { 
     Point p = (Point) o; 
     return(x==p.x && y==p.y); 
    } 
    return false; 
} 
+0

Ho cambiato il mio codice e l'ho ignorato correttamente questa volta e ha risolto il mio problema. Molte grazie. – user1637645

Problemi correlati