2012-01-31 2 views
5

considerare l'aggiunta di un metodo di uguaglianza per la seguente classe di semplici punti:come scrivere un metodo di uguaglianza in Java

public class Point { 

    private final int x; 
    private final int y; 

    public Point(int x, int y) { 
     this.x = x; 
     this.y = y; 
    } 

    public int getX() { 
     return x; 
    } 

    public int getY() { 
     return y; 
    } 

    // ... 
} 

// la mia definizione di eguali

public boolean equals(Point other) { 
    return (this.getX() == other.getX() && this.getY() == other.getY()); 
} 

Cosa c'è di sbagliato con questo metodo? A prima vista, sembra funzionare bene:

Point p1 = new Point(1, 2); 
Point p2 = new Point(1, 2); 

Point q = new Point(2, 3); 

System.out.println(p1.equals(p2)); // prints true 

System.out.println(p1.equals(q)); // prints false 

Tuttavia, guai cominciano una volta di iniziare a mettere punti in una collezione:

import java.util.HashSet; 

HashSet<Point> coll = new HashSet<Point>(); 
coll.add(p1); 

System.out.println(coll.contains(p2)); // prints false 

Come può essere che coll non contiene p2, anche se p1 è stato aggiunto ad esso, e p1 e p2 sono oggetti uguali?

+0

Una buona spiegazione qui: http://bytes.com/topic/java/insights/723476-overriding-equals-hashcode-methods Integra questo - è una delle regole più fondamentali in Java e una domanda frequente di intervista. –

risposta

8

Se è vero che è necessario implementare hashCode() quando si implementa equals(), che non è la causa del problema.

Questo non è il metodo equals() che stai cercando. Il metodo equals deve sempre avere la seguente firma: "public boolean equals (Object object)". Ecco un codice.

Il Apache EqualsBuilder class è utile per le implementazioni uguali.Il collegamento è una versione precedente, ma ancora applicabile.

Se ti è piaciuto l'Apache EqualsBuilder, probabilmente ti piacerà anche lo Apache HashCodeBuilder class.

Modifica: aggiornato l'esempio di metodo equals per le scorciatoie standard.

+1

Suvviato per l'unico post per farlo notare. –

+0

@Louis: Quasi l'unico ... :-) – Dirk

+0

Bene. L'unico come del mio commento che ho visto. –

4

È necessario implementare hashCode() ogni volta che si esegue l'override di equals(). Questi due lavorano insieme e devono dare risultati coerenti in ogni momento. Non farlo produce solo il comportamento errato che hai osservato.

Questo è spiegato in maggior dettaglio, ad es. in Effective Java 2nd Edition, elemento 9: Sostituisci sempre hashCode quando si esegue l'override uguale a.

0

Quando si esegue l'override equals, si hanno anche per sovrascrivere hashCode (in particolare, se avete intenzione di utilizzare HashSet o HashMap ...). Un adatto implementazione (anche se non a intelligente) potrebbe essere:

int hashCode() { 
    return x * 31 + y; 
} 

Un altro punto (no pun intended): non sono in realtà l'override del metodo equals(Object) definito in classe Object, ma invece sta definendo una nuova. Il modo corretto sarebbe:

boolean equals(Object other) { 
    if (other == this) return true; 
    else if (!(other instanceof Point)) return false; 
    else { 
     Point p = (Point)other; 
     return x == p.getX() && y == p.getY(); 
    } 
} 

nota, che il metodo equals ha un pretty strong contract ad esso associati, che si sta per compiere.

1

Come da contratto equals() è necessario implementare anche hashCode().

Dal JavaDoc su equals():

noti che è generalmente necessario ridefinire il metodo hashCode ogniqualvolta viene sovrascritto questo metodo, in modo da mantenere il contratto generale per il metodo hashCode, che afferma che oggetti uguali deve avere codici hash uguali.

1

In aggiunta alle altre risposte:

Se si utilizza Eclipse come IDE, si può semplicemente utilizzare "Sorgente" -> "Generate hashCode() e equals() per ottenere un'implementazione di base che fare. .! che cosa mai si desidera

2

Funziona bene sovrascrivendo hashcode

sempre ricordare:. Override hashCode quando si sovrascrive equals

@Override public int hashCode() { 
     return (41 * (41 + getX()) + getY()); 
    } 

Questa è la mia implementazione di hashCode.

+0

Questo non genera un hash univoco ... 2 esempi semplici 'x = 1',' y = 0', 'Hash = 1722' OR' x = 0', 'y = 41',' Hash = 1722' – Basic