Պատմեք HashMap- ի բախումների մասին։
sobes.tech AI
Պատասխան AI-ից
HashMap-ում բախում առաջանում է, երբ երկու տարբեր բանալիներ ունեն նույն hash-կոդը: Սա չի հանգեցնում տվյալների կորուստի, բայց ազդում է արդյունավետության վրա:
Ամեն անգամ, երբ ավելացվում է տարր՝
- Կոչվում է
hashCode()-ը բանալիի համար: - Հաշվարկվում է բաքի ինդեքսը hash-կոդի հիման վրա:
- Եթե բաքը դատարկ է, տարրն ավելացվում է:
- Եթե բաքը արդեն պարունակում է տարրեր,
equals()-ը կանչվում է յուրաքանչյուր տարրի համար նոր բանալիով: - Եթե
equals()-ը վերադարձնում էtrue, արժեքը թարմացվում է: - Եթե
equals()-ը միշտfalseէ վերադարձնում, նոր տարրն ավելացվում է բաքին:
Նախքան Android 7.0 (Nougat), HashMap-ը օգտագործում էր կապված ցանկեր՝ բախումները լուծելու համար: Երբ բաքում շատ բախումներ լինեն, որոնումը կապված ցանկում դառնում է O(n), որտեղ n — բաքում գտնվող տարրերի քանակը:
Android 7.0-ից հետո, մեծ բախումներ ունեցող բաքերի համար (սահմանաչափ 8 տարր), HashMap-ը ավտոմատ կերպով փոխում է կապված ցանկը կարմիր-սև ծառի (TreeNode)։ Ծառի որոնումը ունի բարդություն O(log n), ինչը զգալիորեն բարելավում է արդյունավետությունը մեծ բախումների դեպքում։ Եթե բաքում տարրերի քանակը կրկին նվազի սահմանաչափից (6 տարր), ծառը վերածվում է կրկին կապված ցանկի:
Լավ hashCode() և equals() իրականացման օրինակ՝ օգտագործվող օբյեկտների համար, կարևոր է բախումների նվազեցման և HashMap-ի արդյունավետության ապահովման համար:
Օրինակ՝
@Override
public int hashCode() {
// Լավ hashCode իրականացման օրինակ
int result = 17;
result = 31 * result + field1.hashCode();
result = 31 * result + field2;
return result;
}
@Override
public boolean equals(Object o) {
// Ճիշտ `equals()` իրականացման օրինակ
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyObject myObject = (MyObject) o;
return field2 == myObject.field2 &&
field1.equals(myObject.field1);
}