Java'da equals() va hashCode() usullarini bekor qilish
Equals
va hashCode
ular sinfda e'lon qilingan Object
va standart Java kutubxonalarida mavjud bo'lgan asosiy usullardir. Usul ob'ektlarni solishtirish va ob'ekt uchun butun son kodini yaratish uchun еquals()
ishlatiladi . hashCode
Ushbu usullar Java standart kutubxonalarida ob'ektlarni kiritish va olishda keng qo'llaniladi HashMap
. Usul, shuningdek, boshqa ilovalarda, shuningdek, ob'ektlarni solishtirish kerak bo'lgan boshqa holatlarda equal
faqat noyob ob'ektlar saqlanishini ta'minlash uchun ishlatiladi . Sinfdagi usulning sukut bo'yicha amalga oshirilishi o'zgaruvchilar saqlaydigan xotira manzillariga havolalarni solishtiradi va manzillar mos kelsagina qaytaradi, boshqacha qilib aytganda, o'zgaruvchilar bir xil ob'ektga murojaat qiladi. Agar taqqoslash tabiiy mantiq yoki biznes mantiqiga muvofiq amalga oshirilishini kutsangiz, Java va usullarini bekor qilishni tavsiya qiladi. Standart Java kutubxonalaridagi ko'pgina sinflar ularni bekor qiladi, masalan, sinf o'z o'rnini bosadi , shuning uchun solishtirilayotgan ikkita ob'ektning mazmuni bir xil bo'lsa, u qaytib keladi. O'rash sinfi raqamli taqqoslashni amalga oshirish usulini bekor qiladi va hokazo. Java ularning va ni solishtirish usullariga ham tayanganligi sababli , Java ushbu usullarni bekor qilish uchun quyidagi qoidalarni taklif qiladi: HashSet
Set
equals()
java.lang.Object
true
equals()
hashCode()
String
equals
true
Integer
equal
HashMap
HashTable
equals()
hashCode()
key
values
- Reflektorlik: ob'ekt o'ziga teng bo'lishi kerak.
- Simmetrik: agar
a.equals(b)
u qaytsatrue
,b.equals(a)
u ham qaytishi keraktrue
. - Tranzitivlik: agar
a.equals(b)
u qaytsatrue
vab.equals(c)
yana qaytarsatrue
,c.equals(a)
u ham qaytishi keraktrue
. - Muvofiqlik: Usulga takroriy qo'ng'iroqlar,
equals()
ob'ektning ba'zi xususiyat qiymatlari o'zgarmas ekan, bir xil qiymatni qaytarishi kerak. Ya'ni, agar Java-da ikkita ob'ekt teng bo'lsa, ularning xususiyatlari o'zgarmas ekan, ular teng bo'ladi. - Taqqoslash
null
: ob'ektni tekshirish keraknull
. Agar ob'ekt ga teng bo'lsanull
, u holda usulfalse
emas, balki qaytishi kerakNullPointerException
. Masalan,a.equals(null)
u qaytishi kerakfalse
.
Java'da tenglar va hashCode o'rtasidagi kelishuv
- Agar ob'ektlar usulni bajarish natijalarida teng bo'lsa
equals
, ularhashcode
bir xil bo'lishi kerak. - Agar ob'ektlar usulni bajarish natijalarida teng bo'lmasa
equals
, ularhashcode
bir xil yoki boshqacha bo'lishi mumkin. Biroq, ishlashni yaxshilash uchun turli ob'ektlar turli xil kodlarni qaytarishi yaxshiroqdir.
Java'da teng usulini qanday bekor qilish mumkin
-
@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
va kabi oʻrash sinflariInteger
va usulini bekor qiladiFloat
, lekin bekor qilmaydi.Double
equals()
StringBuffer
-
Iloji bo'lsa, Java-da o'zgaruvchilardan
immutable
foydalanib, maydonlarni yaratingfinal
. -
String
Ob'ektlarni taqqoslashdaequals()
. operatoridan foydalaning==
. -
Mantiqiy jihatdan teng bo'lgan, lekin turli ob'ektlardan yuklangan ikkita ob'ekt
ClassLoader
teng bo'lishi mumkin emas. Esda tutingki, agar yuklovchi sinfi boshqacha bo'lsa, bilan tekshirishgetClass()
qaytadi .false
-
@Override
Izohdan . usulida ham foydalaninghashCode
, chunki bu ning qaytarilish qiymati kabi nozik xatolarning oldini oladiint
Biroq, ba'zi dasturchilar qaytadilong
.
GO TO FULL VERSION