Mengganti metode sama dengan() dan kode hash() di Java
Equals
dan hashCode
merupakan metode dasar yang dideklarasikan di kelas Object
dan terdapat dalam perpustakaan Java standar. Metode ini еquals()
digunakan untuk membandingkan objek dan hashCode
menghasilkan kode integer untuk objek tersebut. Metode ini banyak digunakan di perpustakaan standar Java saat menyisipkan dan mengambil objek dalam format HashMap
. Metode ini equal
juga digunakan untuk memastikan bahwa hanya objek unik yang disimpan dalam implementasi HashSet
lain Set
, serta dalam kasus lain di mana objek perlu dibandingkan. Implementasi default metode equals()
di kelas java.lang.Object
membandingkan referensi ke alamat memori yang disimpan dan dikembalikan oleh variabel true
hanya jika alamatnya cocok, dengan kata lain, variabel merujuk ke objek yang sama. Java merekomendasikan untuk mengganti metode equals()
and hashCode()
jika Anda mengharapkan perbandingan dilakukan berdasarkan logika natural atau logika bisnis. Banyak kelas di perpustakaan Java standar yang menimpanya, misalnya kelas tersebut String
menimpa equals
sehingga kembali true
jika isi kedua objek yang dibandingkan sama. Kelas wrapper mengambil alih Integer
metode equal
untuk melakukan perbandingan numerik, dan seterusnya. Karena Java HashMap
juga mengandalkan metode dan untuk membandingkan dan , Java menawarkan aturan berikut untuk mengganti metode ini: HashTable
equals()
hashCode()
key
values
- Refleksivitas: Objek harus sama dengan dirinya sendiri.
- Simetris: jika
a.equals(b)
kembalitrue
, makab.equals(a)
harus kembali jugatrue
. - Transitivitas: jika
a.equals(b)
ia kembalitrue
danb.equals(c)
juga kembalitrue
, makac.equals(a)
ia juga harus kembalitrue
. - Konsistensi: Panggilan berulang ke suatu metode
equals()
harus mengembalikan nilai yang sama selama beberapa nilai properti objek tidak berubah. Artinya, jika dua objek sama di Java, maka keduanya akan sama selama propertinya tidak berubah. - Perbandingan
null
: Objek harus diperiksanull
. Jika objeknya sama dengannull
, maka metode tersebut harus mengembalikanfalse
, bukanNullPointerException
. Misalnya,a.equals(null)
ia harus mengembalikanfalse
.
Perjanjian antara sama dengan dan kode hash di Java
- Jika objek-objeknya sama dalam hasil eksekusi metode
equals
, maka objek-objek tersebuthashcode
harus sama. - Jika objek-objek tersebut tidak sama dalam hasil eksekusi metode
equals
, maka objek-objek tersebuthashcode
dapat sama atau berbeda. Namun, untuk meningkatkan kinerja, lebih baik objek yang berbeda mengembalikan kode yang berbeda.
Cara mengganti metode yang sama di Java
-
@Override public boolean equals(Object obj) { /*1. Check*/
if (obj == this) { /*and return */ return true; }
-
Проверьте an object на
null
, а также проверьте, чтобы an objectы были одного типа. Не делайте проверку с помощьюinstanceof
так How такая проверка будет возвращатьtrue
для подклассов и будет работать правильно только в случае если ваш класс объявлен Howimmutable
. Вместо этого можно использовать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
определен Howpublic boolean equals(Object obj)
, но многие программисты ненароком перегружают метод:public boolean equals(Person obj)
- instead ofObject
в качестве аргумента используют Name своего класса (напр. Person). Эту ошибку сложно обнаружить из-заstatic binding
. Таким образом, если вы вызовете этот метод для an object своего класса, то метод не просто скомпorруется, а даже сделает это корректно. Однако, если вы положите ваш an object в коллекцию, напримерArrayList
и вызовете методcontains()
, работа которого основана на методеequals()
, то методcontains
не сможет обнаружить ваш an object. -
При переопределении метода
equals()
не проверять наnull
переменные, что в конечном итоге заканчиваетсяNullPointerException
при вызовеequals()
. Ниже представлен корректный code.firstname == guest.firstname || (firstname != null && firstname.equals(guest.firstname));
-
Третья распространенная ошибка это не переопределять метод
hashCode()
, а толькоequals()
. Вы обязаны переопределять оба методаequals()
иhashCode()
в Java. МетодhashCode
используется вhash
-коллекциях(напримерHashSet
), и чем меньше будет коллизий (одинаковый code при разных an objectх) тем эффективнее эти коллекции будут работать с an objectми вашего класса. -
Последняя распространенная ошибка программистов в том, что при переопределении метода
equals()
не сохраняется соответствие между методамиequals()
иcompareTo()
, что является неформальным требованием для избежания хранения дубликатов вSet (SortedSet, TreeSet)
.
Подсказки How писать в Java метод equals
-
Большинство IDE такие How NetBeans, Eclipse и IntelliJ IDEA обеспечивают поддержку генерации методов
equals()
иhashCode()
. В Eclipse нажмите правую кнопку -> source ->generate equals()
иhashCode()
. -
Если в классе есть уникальный бизнес-ключ, то будет достаточно сделать проверку только на equalsство этих полей. Как в нашем примере “id” - уникальный номер для каждого Person.
-
При переопределении
hashCode()
в Java удостоверьтесь в использовании всех полей, что были использованы в методеequals()
. -
String
dan kelas pembungkus sepertiInteger
,Float
danDouble
mengganti metodeequals()
, tetapiStringBuffer
tidak menimpa. -
Jika memungkinkan, buat kolom
immutable
menggunakanfinal
variabel di Java. -
Saat membandingkan
String
objek, gunakanequals()
operator .sebagai gantinya==
. -
Dua objek yang secara logis sama tetapi diambil dari objek yang berbeda
ClassLoader
tidak bisa sama. Ingatlah bahwa pengecekan dengangetClass()
akan kembalifalse
jika kelas pemuat berbeda. -
Gunakan
@Override
juga anotasi pada metode .hashCode
, karena ini mencegah kesalahan halus seperti nilai kembalian .Namunint
, beberapa pemrogram mengembalikanlong
.
GO TO FULL VERSION