Anulando los métodos equals() y hashCode() en Java
Equals
y hashCode
son los métodos fundamentales declarados en la clase Object
y contenidos en las bibliotecas estándar de Java. El método еquals()
se utiliza para comparar objetos y hashCode
generar un código entero para el objeto. Estos métodos se utilizan ampliamente en las bibliotecas estándar de Java al insertar y recuperar objetos en formato HashMap
. El método equal
también se utiliza para garantizar que solo se almacenen objetos únicos en HashSet
otras Set
implementaciones, así como en cualquier otro caso en el que sea necesario comparar objetos. La implementación predeterminada del método equals()
en la clase java.lang.Object
compara referencias a las direcciones de memoria que almacenan las variables y devuelve true
solo si las direcciones coinciden, en otras palabras, las variables se refieren al mismo objeto. Java recomienda anular los métodos equals()
y hashCode()
si espera que la comparación se realice según la lógica natural o la lógica empresarial. Muchas clases en las bibliotecas estándar de Java los anulan, por ejemplo, la clase String
anula equals
para que devuelva true
si el contenido de los dos objetos que se comparan es el mismo. La clase contenedora anula Integer
el método equal
para realizar una comparación numérica, y así sucesivamente. Dado que Java HashMap
también se basa en métodos y para comparar sus y , Java ofrece las siguientes reglas para anular estos métodos: HashTable
equals()
hashCode()
key
values
- Reflexividad: El objeto debe ser igual a sí mismo.
- Simétrico: si
a.equals(b)
devuelvetrue
, entoncesb.equals(a)
también debe devolvertrue
. - Transitividad: si
a.equals(b)
regresatrue
yb.equals(c)
también regresatrue
, entoncesc.equals(a)
también debe regresartrue
. - Consistencia: las llamadas repetidas a un método
equals()
deben devolver el mismo valor siempre que no se cambien algunos de los valores de propiedad del objeto. Es decir, si dos objetos son iguales en Java, serán iguales siempre que sus propiedades permanezcan sin cambios. - Comparación
null
: Se debe comprobar el objetonull
. Si el objeto es igual anull
, entonces el método debería devolverfalse
, noNullPointerException
. Por ejemplo,a.equals(null)
debería devolverfalse
.
Acuerdo entre iguales y hashCode en Java
- Si los objetos son iguales en los resultados de la ejecución del método
equals
, entonceshashcode
deben ser iguales. - Si los objetos no son iguales en los resultados de la ejecución del método
equals
, entonceshashcode
pueden ser iguales o diferentes. Sin embargo, para mejorar el rendimiento, es mejor que diferentes objetos devuelvan códigos diferentes.
Cómo anular el método igual en Java
-
@Override public boolean equals(Object obj) { /*1. Controlar*/
if (obj == this) { /*y volver */ return true; }
-
Проверьте un objeto на
null
, а также проверьте, чтобы un objetoы были одного типа. Не делайте проверку с помощьюinstanceof
так Cómo такая проверка будет возвращатьtrue
для подклассов и будет работать правильно только в случае если ваш класс объявлен Cómoimmutable
. Вместо этого можно использоватьgetClass()
;if (obj == null || obj.getClass() != this.getClass()) { return false; }
-
Объявите переменную типа, который вы сравниваете, и приведите
obj
к этому типу. Потом сравнивайте каждый атрибут типа начиная с численных атрибутов (если имеются) потому что численные атрибуты проверяются быстрей. Сравнивайте атрибуты с помощью операторов И и ИЛИ (так называемыеshort-circuit logical operators
) для объединения проверок с другими атрибутами.Person guest = (Person) obj; return id == guest.id && (firstName == guest.firstName || (firstName != null && firstName.equals(guest.getFirstName()))) && (lastName == guest.lastName || (lastName != null && lastName .equals(guest.getLastName()))); }
/** * Person class with equals and hashcode implementation in Java * @author Javin Paul */
public class Person {
private int id;
private String firstName;
private String lastName;
public int getId() { return id; }
public void setId(int id) { this.id = id;}
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) { this.firstName = firstName; }
public String getLastName() { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || obj.getClass() != this.getClass()) {
return false;
}
Person guest = (Person) obj;
return id == guest.id
&& (firstName == guest.firstName
|| (firstName != null &&firstName.equals(guest.getFirstName()))) && (lastName == guest.lastName
|| (lastName != null && lastName .equals(guest.getLastName())
));
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); result = prime * result + id; result = prime * result +
((lastName == null) ? 0 : lastName.hashCode()); return result;
}
}
Распространенные ошибки при переопределении equals в Java
-
Вместо того, чтобы переопределять метод
equals (Override)
программист перегружает его(Overload)
Синтаксис методаequals()
в классеObject
определен Cómopublic boolean equals(Object obj)
, но многие программисты ненароком перегружают метод:public boolean equals(Person obj)
- en lugar deObject
в качестве аргумента используют Nombre своего класса (напр. Person). Эту ошибку сложно обнаружить из-заstatic binding
. Таким образом, если вы вызовете этот метод для un objetoа своего класса, то метод не просто скомпoруется, а даже сделает это корректно. Однако, если вы положите ваш un objeto в коллекцию, напримерArrayList
и вызовете методcontains()
, работа которого основана на методеequals()
, то методcontains
не сможет обнаружить ваш un objeto. -
При переопределении метода
equals()
не проверять наnull
переменные, что в конечном итоге заканчиваетсяNullPointerException
при вызовеequals()
. Ниже представлен корректный código.firstname == guest.firstname || (firstname != null && firstname.equals(guest.firstname));
-
Третья распространенная ошибка это не переопределять метод
hashCode()
, а толькоequals()
. Вы обязаны переопределять оба методаequals()
иhashCode()
в Java. МетодhashCode
используется вhash
-коллекциях(напримерHashSet
), и чем меньше будет коллизий (одинаковый código при разных un objetoах) тем эффективнее эти коллекции будут работать с un objetoами вашего класса. -
Последняя распространенная ошибка программистов в том, что при переопределении метода
equals()
не сохраняется соответствие между методамиequals()
иcompareTo()
, что является неформальным требованием для избежания хранения дубликатов вSet (SortedSet, TreeSet)
.
Подсказки Cómo писать в Java метод equals
-
Большинство IDE такие Cómo NetBeans, Eclipse и IntelliJ IDEA обеспечивают поддержку генерации методов
equals()
иhashCode()
. В Eclipse нажмите правую кнопку -> source ->generate equals()
иhashCode()
. -
Если в классе есть уникальный бизнес-ключ, то будет достаточно сделать проверку только на es igualство этих полей. Как в нашем примере “id” - уникальный номер для каждого Person.
-
При переопределении
hashCode()
в Java удостоверьтесь в использовании всех полей, что были использованы в методеequals()
. -
String
y clases contenedoras comoInteger
y anulan el método , pero no anulan.Float
Double
equals()
StringBuffer
-
Siempre que sea posible, cree campos
immutable
usandofinal
variables en Java. -
Al comparar
String
objetos, utiliceequals()
el operador .en su lugar==
. -
Dos objetos que son lógicamente iguales pero cargados desde objetos diferentes
ClassLoader
no pueden ser iguales. Recuerde que consultar congetClass()
volveráfalse
si la clase del cargador es diferente. -
Utilice
@Override
la anotación también en el método .hashCode
, ya que esto evita errores sutiles como el valor de retorno del métodoint
.Sin embargo, algunos programadores devuelvenlong
.
GO TO FULL VERSION