2012-01-31 11 views
5

considerar la adición de un método de igualdad, a las siguientes clases de puntos simples:cómo escribir un método de Igualdad en 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; 
    } 

    // ... 
} 

// mi definición de iguales

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

¿Qué pasa con este método? A primera vista, parece que funciona bien:

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 

Sin embargo, los problemas se inicia una vez que comience a poner puntos en una colección:

import java.util.HashSet; 

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

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

¿Cómo puede ser que coll no contiene p2, aunque se le agregó p1, y p1 y p2 son objetos iguales?

+0

Buena explicación aquí: http://bytes.com/topic/java/insights/723476-overriding-equals-hashcode-methods Internalize this - es una de las reglas más fundamentales en Java y una pregunta frecuente de la entrevista. –

Respuesta

8

Si bien es cierto que se debe implementar hashCode() al implementar equals(), que no está causando el problema.

Ese no es el método equals() que está buscando. El método equals siempre debe tener la siguiente firma: "public boolean equals (Object object)". Aquí hay un código.

public boolean equals(Object object) 
{ 
    if (object == null) 
    { 
    return false; 
    } 

    if (this == object) 
    { 
    return true; 
    } 

    if (object instanceof Point) 
    { 
    Point point = (Point)object; 
    ... now do the comparison. 
    } 
    else 
    { 
    return false; 
    } 
} 

El Apache EqualsBuilder class es útil para implementaciones equals.El enlace es una versión anterior, pero sigue siendo aplicable.

Si te gusto el EqualsBuilder de Apache, es probable que también te guste el Apache HashCodeBuilder class.

Edit: actualizó el ejemplo del método equals para atajos estándar.

+1

Subida de la única publicación que señala esto. –

+0

@Louis: Casi el único ... :-) – Dirk

+0

Bueno. El único de mi comentario que vi. –

4

Debe implementar hashCode() siempre que anule equals(). Estos dos trabajan juntos, y deben dar resultados consistentes todo el tiempo. Si no lo hace, solo produce el comportamiento erróneo que observó.

Esto se explica con más detalle, p. en Effective Java 2nd Edition, artículo 9: Anule siempre el código hash cuando invalide equivale a.

0

Al reemplazar equals, también hay que anular hashCode (en particular, si se va a utilizar HashSet o HashMap ...). Una implementación adecuada (aunque no inteligente) sería:

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

Otro punto (sin doble sentido): No en realidad se está reemplazando el método definido en la clase equals(Object)Object, sino que está definiendo una nueva. La forma correcta sería:

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(); 
    } 
} 

Tenga en cuenta, que el método tiene un equalspretty strong contract asociado a él, que desea cumplir.

1

Según el contrato en equals() necesita implementar hashCode() también.

Desde el JavaDoc en equals():

Tenga en cuenta que en general es necesario reemplazar el método hashCode cada vez que se anula este método, a fin de mantener el contrato general para el método hashCode, que establece que la igualdad de los objetos debe tener los mismos códigos hash.

1

Además de las otras respuestas:

Si está utilizando Eclipse como IDE, puede simplemente usar "Fuente" -> "Generar hashCode() y equals() para obtener una implementación básica hacer con él. .! que cualquier cosa que quiera

2

Funciona bien anulando código hash

recuerde siempre:. anulación hashCode cuando se reemplaza iguales

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

Esta es mi implementación de hashCode.

+0

Esto no genera un hash único ... 2 ejemplos simples 'x = 1',' y = 0', 'Hash = 1722' O' x = 0', 'y = 41',' Hash = 1722' – Basic

Cuestiones relacionadas