Java'дагы equals() жана hashCode() ыкмаларын жокко чыгаруу
Equals
жана hashCode
класста жарыяланган Object
жана стандарттуу Java китепканаларында камтылган негизги методдор. Метод an objectтерди салыштыруу жана an object үчүн бүтүн codeду түзүү үчүн еquals()
колдонулат . hashCode
Бул ыкмалар Java стандарттык китепканаларында an objectтерди киргизүүдө жана алууда кеңири колдонулат HashMap
. Метод ошондой эле башка ишке ашырууларда, ошондой эле an objectтерди салыштыруу керек болгон башка учурларда equal
гана уникалдуу an objectтер сакталышын камсыз кылуу үчүн колдонулат . Методдун класстагы демейки ишке ашырылышы өзгөрмөлөр сактаган эстутум даректерине шилтемелерди салыштырат жана даректер дал келген учурда гана кайтарат, башкача айтканда, өзгөрмөлөр бир эле an objectке кайрылат. Салыштыруу табигый логикага же бизнес логикасына ылайык жасалышын күтсөңүз, Java жана методдорун жокко чыгарууну сунуштайт. Стандарттык Java китепканаларындагы көптөгөн класстар аларды жокко чыгарат, мисалы класс, салыштырылып жаткан эки an objectтин мазмуну бирдей болсо, ал кайтып келгидей кылып жокко чыгарат . Ороочу классы сандык салыштырууну жүргүзүү ыкмасын жокко чыгарат жана башкалар. Java да алардын жана менен салыштыруу ыкмаларына таянгандыктан , Java бул ыкмаларды жокко чыгаруу үчүн төмөнкү эрежелерди сунуштайт: HashSet
Set
equals()
java.lang.Object
true
equals()
hashCode()
String
equals
true
Integer
equal
HashMap
HashTable
equals()
hashCode()
key
values
- Reflexivity: an object өзүнө барабар болушу керек.
- Симметриялуу: эгерде
a.equals(b)
ал кайтып келсеtrue
, андаb.equals(a)
ал да кайтып келиши керекtrue
. - Өтмөлүк: эгерде
a.equals(b)
ал кайтып келсеtrue
жанаb.equals(c)
ошондой эле кайтып келсеtrue
, андаc.equals(a)
ал да кайтып келиши керекtrue
. - Ыйгарымдуулук: методго кайталанган чалуулар
equals()
an objectтин кээ бир менчик баалуулуктары өзгөртүлбөсө, ошол эле маанини кайтарышы керек. Башкача айтканда, Java тorнде эки an object бирдей болсо, анда алардын касиеттери өзгөрүүсүз калганда, алар бирдей болот. - Салыштыруу
null
: an object текшерorши керекnull
. Эгерде an object ге барабар болсоnull
, анда методfalse
эмес, кайтып келиши керекNullPointerException
. Мисалы,a.equals(null)
ал кайтып келиши керекfalse
.
Java тorндеги тең жана hashCode ортосундагы макулдашуу
- Эгерде an objectтер методдун аткарылышынын жыйынтыгы боюнча бирдей болсо
equals
, анда аларhashcode
бирдей болушу керек. - Эгерде an objectтер методдун аткарылышынын жыйынтыгы боюнча бирдей болбосо
equals
, анда аларhashcode
бирдей же ар башка болушу мүмкүн. Бирок, ишти жакшыртуу үчүн, ар кандай an objectтер ар кандай codeдорду кайтарып бергени жакшы.
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
Integer
жана , сыяктуу орогуч класстарыFloat
жанаDouble
методду жокко чыгаратequals()
, бирокStringBuffer
жокко чыгарbyte. -
Мүмкүн болушунча Java'да өзгөрмөлөрдү
immutable
колдонуп талааларды түзүңүз.final
-
String
Объекттерди салыштырганда ,equals()
анын ордуна . операторун колдонуңуз==
. -
Логикалык жактан бирдей, бирок ар башка an objectтерден жүктөлгөн эки an object
ClassLoader
бирдей боло алbyte. Эгер жүктөгүч классы башка болсо, текшерүүgetClass()
кайтып келерин унутпаңыз.false
-
@Override
Аннотацияны .методунда да колдонуңузhashCode
, анткени бул .мезгилдин кайтаруу мааниси сыяктуу тымызын каталардын алдын алат.Бирокint
, кээ бир программисттер кайра кайтарышатlong
.
GO TO FULL VERSION