Ինչու է կարևոր Java-ում վերագրել equals և hashCode մեթոդները:
sobes.tech AI
Պատասխան AI-ից
equals և hashCode-ի վերանվանումը կարևոր է օբյեկտների ճիշտ աշխատանքի համար հավաքածուներում և համեմատության ժամանակ:
- Սիմետրիկություն: Եթե
a.equals(b)վերադարձնում էtrue, ապաb.equals(a)նույնպես պետք է լինիtrue: - Ռեֆլեկտիվություն: Ամեն մի ոչ զրոյական օբյեկտ
aհամար,a.equals(a)պետք է լինիtrue: - Տրանզիտիվություն: Եթե
a.equals(b)ևb.equals(c)վերադարձնում ենtrue, ապաa.equals(c)նույնպես պետք է լինիtrue: - Կոնսիստենտություն: Շատ անգամ
a.equals(b)կանչերը պետք է կայունորեն վերադարձնենtrueկամfalse, եթեequals-ում օգտագործված տեղեկությունները չեն փոխվել:
hashCode-ի համար:
- Կոնսիստենտություն: Եթե
equals-ում օգտագործված տեղեկությունները չեն փոխվել, ապաhashCode-ի բազմակի կանչերը պետք է վերադարձնեն նույն ամբողջական թիվը: - Կապ
equals-ի հետ: Եթե երկու օբյեկտներ համընկնում ենequals-ի համաձայն, ապա նրանցhashCode-ը պետք է լինի նույնը: - Օպտիմալացում: Չի պահանջվում, որ եթե երկու օբյեկտներ չեն համընկնում
equals-ի համաձայն, նրանցhashCode-ը տարբեր լինի, բայց տարբերhashCode-ներ ստեղծելը կարող է բարելավել հեշ-թաբլետների կատարողականությունը:
Այս կանոնների խախտումը կարող է հանգեցնել անսպասելի վարքագծի, երբ օգտագործվում են HashSet, HashMap, ArrayList և այլ հավաքածուներ, որոնք հիմնված են այս մեթոդների ճիշտ իրականացման վրա՝ օբյեկտների հավասարության և տեղադրության ճիշտ որոշման համար:
Օրինակ՝
// Օրինակ՝ դաս առանց ճիշտ `equals` և `hashCode`
class PersonBroken {
private String name;
private int age;
public PersonBroken(String name, int age) {
this.name = name;
this.age = age;
}
// getter-ներ բաց թողնված՝ կարճության համար
}
// Օրինակ՝ դաս ճիշտ `equals` և `hashCode`-ով
class PersonCorrect {
private String name;
private int age;
public PersonCorrect(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PersonCorrect that = (PersonCorrect) o;
return age == that.age &&
Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
// getter-ներ բաց թողնված՝ կարճության համար
}
// Օգտագործում հավաքածուում
List<PersonBroken> brokenList = new ArrayList<>();
brokenList.add(new PersonBroken("Alice", 30));
System.out.println(brokenList.contains(new PersonBroken("Alice", 30))); // Հավանաբար՝ false
List<PersonCorrect> correctList = new ArrayList<>();
correctList.add(new PersonCorrect("Alice", 30));
System.out.println(correctList.contains(new PersonCorrect("Alice", 30))); // Հավանաբար՝ true
Set<PersonBroken> brokenSet = new HashSet<>();
brokenSet.add(new PersonBroken("Bob", 25));
brokenSet.add(new PersonBroken("Bob", 25));
System.out.println(brokenSet.size()); // Հավանաբար՝ 2
Set<PersonCorrect> correctSet = new HashSet<>();
correctSet.add(new PersonCorrect("Bob", 25));
correctSet.add(new PersonCorrect("Bob", 25));
System.out.println(correctSet.size()); // Հավանաբար՝ 1
Օրինակ՝ PersonBroken-ի դեպքում, նույն դաշտերի արժեքներով օբյեկտները համարվում են տարբեր, քանի որ օգտագործվում են equals-ի դեֆոլտային (համեմատում է հղումները) և hashCode-ի (գեներացվում է օբյեկտի հասցեով) իրականացումները: PersonCorrect-ի դեպքում, վերագրած մեթոդները թույլ են տալիս հավաքածուներին ճիշտ որոշել օբյեկտների հավասարությունը նրանց պարունակության հիման վրա։