"Ngayon sasabihin ko sa iyo ang tungkol sa ilang mga pamamaraan na kapaki-pakinabang din:  equals(Object o) & hashCode() ."

"Marahil ay naalala mo na, sa Java, kapag inihahambing ang mga sangguniang variable ang mga bagay mismo ay hindi inihambing, ngunit sa halip ang mga sanggunian sa mga bagay."

Code Paliwanag
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i==j);
i ay hindi katumbas ng j
Ang mga variable ay tumuturo sa iba't ibang mga bagay.
Kahit na ang mga bagay ay naglalaman ng parehong data.
Integer i = new Integer(1);
Integer j = i;
System.out.println(i==j);
katumbas ko si j. Ang mga variable ay naglalaman ng isang sanggunian sa parehong bagay.

"Oo, naalala ko iyon."

Ang  mga katumbas .

"Ang equals method ay ang karaniwang solusyon dito. Ang layunin ng equals method ay upang matukoy kung ang mga bagay ay panloob na magkapareho sa pamamagitan ng paghahambing ng kung ano ang nakaimbak sa loob ng mga ito."

"At paano nito ginagawa iyon?"

"Ang lahat ng ito ay halos kapareho sa toString() na pamamaraan."

Ang klase ng Bagay ay may sariling pagpapatupad ng equals method, na naghahambing lamang ng mga sanggunian:

public boolean equals(Object obj)
{
return (this == obj);
}

"Great... back to that again, tayo ba?"

"Itaas baba mo! Sa totoo lang nakakalito."

"Ginawa ang paraang ito upang payagan ang mga developer na i-overwrite ito sa sarili nilang mga klase. Pagkatapos ng lahat, ang developer lang ng isang klase ang nakakaalam kung anong data ang may kaugnayan at kung ano ang hindi kapag naghahambing."

"Maaari ka bang magbigay ng isang halimbawa?"

"Oo naman. Ipagpalagay na mayroon tayong klase na kumakatawan sa mga mathematical fraction. Ito ay magiging ganito:"

Halimbawa:
class Fraction
{
private int numerator;
private int denominator;
Fraction(int numerator, int denominator)
{
this.numerator  = numerator;
this.denominator = denominator;
}public boolean equals(Object obj)
{
if (obj==null)
return false;

if (obj.getClass() != this.getClass() )
return false;

Fraction other = (Fraction) obj;
return this.numerator* other.denominator == this.denominator * other.numerator;
}
}
Halimbawang paraan ng tawag:
Fraction one = new Fraction(2,3);
Fraction two = new Fraction(4,6);
System.out.println(one.equals(two));
Magbabalik true ang method call.
Ang fraction 2/3 ay katumbas ng fraction 4/6

"Ngayon, hatiin natin ang halimbawang ito."

"Na-overrode namin ang equals method, kaya magkakaroon ng sariling pagpapatupad ang mga Fraction object.

"May ilang mga pagsusuri sa pamamaraan:"

" 1)  Kung ang bagay na ipinasa para sa paghahambing ay null , kung gayon ang mga bagay ay hindi pantay. Kung maaari mong tawagan ang katumbas na paraan sa isang bagay, kung gayon ito ay tiyak na hindi null ."

" 2)  Isang paghahambing ng klase. Kung ang mga bagay ay mga pagkakataon ng iba't ibang klase, hindi namin susubukang ihambing ang mga ito. Sa halip, gagamit kami kaagad ng return false upang ipahiwatig na ang mga ito ay magkaibang mga bagay."

" 3)  Naaalala ng lahat mula sa ikalawang baitang na ang 2/3 ay katumbas ng 4/6. Ngunit paano mo masusuri iyon?"

2/3 == 4/6
I-multiply natin ang magkabilang panig ng parehong divisors (6 at 3), at makuha natin ang:
6 * 2 == 4 * 3
12 == 12
Pangkalahatang tuntunin:
Kung
a / b == c / d
Pagkatapos ay
a * d == c * b

"Alinsunod dito, sa ikatlong bahagi ng equals method, inihagis namin ang naipasa na bagay sa isang Fraction at inihambing ang mga fraction."

"Got it. Kung ihahambing lang natin ang numerator sa numerator at ang denominator sa denominator, kung gayon ang 2/3 ay hindi katumbas ng 4/6."

"Ngayon naiintindihan ko na kung ano ang ibig mong sabihin noong sinabi mong developer lang ng isang klase ang nakakaalam kung paano ito ikumpara nang tama."

"Oo, ngunit kalahati lang iyon ng kwento.  May isa pang paraan: hashCode(). "

"Lahat ng bagay tungkol sa equals method ay may katuturan ngayon, ngunit bakit kailangan natin ng  hashCode ()? "

"Ang pamamaraan ng hashCode ay kailangan para sa mabilis na paghahambing."

"Ang equals method ay may malaking downside: ito ay gumagana nang masyadong mabagal. Ipagpalagay na mayroon kang isang Set ng milyun-milyong elemento at kailangan mong suriin kung naglalaman ito ng isang partikular na bagay. Paano mo gagawin iyon?"

"Maaari kong paikutin ang lahat ng elemento gamit ang isang loop at ikumpara ang bagay sa bawat bagay sa set. Hanggang sa makakita ako ng tugma."

"At kung wala? We'd perform a million comparisons just to find out that the object isn't there? Hindi ba parang marami iyon?"

"Oo, kahit ako kinikilala ko na napakaraming paghahambing. Mayroon bang ibang paraan?"

"Oo, maaari mong gamitin ang hashCode () para dito.

Ang pamamaraan ng hashCode () ay nagbabalik ng isang tiyak na numero para sa bawat bagay. Ang developer ng isang klase ay nagpapasya kung anong numero ang ibinalik, tulad ng ginagawa niya para sa equals na paraan.

"Tingnan natin ang isang halimbawa:"

"Isipin na mayroon kang isang milyong 10-digit na numero. Pagkatapos, maaari mong gawing ang hashCode ng bawat numero ang natitira pagkatapos hatiin ang numero sa 100."

Narito ang isang halimbawa:

Numero Ang aming hashCode
1234567890 90
9876554321 21
9876554221 21
9886554121 21

"Yeah, that makes sense. At ano ang gagawin natin sa hashCode na ito?"

"Sa halip na ihambing ang mga numero, inihahambing namin ang kanilang mga hashCode . Mas mabilis iyon sa ganoong paraan."

"At tinatawagan namin ang mga katumbas lamang kung ang kanilang mga hashCode ay pantay."

"Oo, mas mabilis iyon. Ngunit kailangan pa rin nating gumawa ng isang milyong paghahambing. Nagkukumpara lang tayo ng mas maliliit na numero, at kailangan pa rin nating tumawag ng mga katumbas para sa anumang mga numero na may katugmang mga hashCode."

"Hindi, maaari kang makatakas sa mas maliit na bilang ng mga paghahambing."

"Isipin na ang aming Set ay nag-iimbak ng mga numerong naka-grupo o pinagsunod-sunod ayon sa hashCode (ang pag-uuri sa mga ito sa paraang ito ay mahalagang pagpapangkat-pangkat sa kanila, dahil ang mga numero na may parehong hashCode ay magkakatabi). Pagkatapos ay maaari mong napakabilis at madaling itapon ang mga hindi nauugnay na grupo. Ito ay sapat na upang suriin nang isang beses bawat pangkat upang makita kung ang hashCode nito ay tumutugma sa hashCode ng object."

"Isipin mo na ikaw ay isang estudyante na naghahanap ng isang kaibigan na makikilala mo sa pamamagitan ng paningin at na alam naming nakatira sa Dorm 17. Pagkatapos ay pupunta ka lang sa bawat dorm sa unibersidad at magtatanong, 'Ito ba ang Dorm 17?' Kung hindi, pagkatapos ay hindi mo papansinin ang lahat sa dorm at lumipat sa susunod. Kung ang sagot ay 'oo', pagkatapos ay magsisimula kang maglakad sa bawat isa sa mga silid, hinahanap ang iyong kaibigan."

"Sa halimbawang ito, ang numero ng dorm (17) ay ang hashCode."

"Dapat alam ng isang developer na nagpapatupad ng hashCode function ang sumusunod:"

A)  dalawang magkaibang bagay ay maaaring magkaroon ng parehong hashCode  (maaaring manirahan ang iba't ibang tao sa parehong dorm)

B)  ang mga bagay na pareho  ( ayon sa paraan ng katumbasay dapat magkaroon ng parehong hashCode. .

C)  ang mga hash code ay dapat mapili upang walang maraming iba't ibang mga bagay na may parehong hashCode.  Kung mayroon, mawawala ang mga potensyal na pakinabang ng hashcodes (Pumunta ka sa Dorm 17 at malalaman na kalahati ng unibersidad ang nakatira doon. Bummer!).

"At ngayon ang pinakamahalagang bagay. Kung i-override mo ang equals na paraan, talagang dapat mong i-override ang hashCode () na paraan at sumunod sa tatlong panuntunang inilarawan sa itaas.

"Ang dahilan ay ito: sa Java, ang mga bagay sa isang koleksyon ay palaging inihahambing/kinukuha gamit ang hashCode() bago sila ikumpara/kinukuha gamit ang mga katumbas.  At kung ang magkaparehong mga bagay ay may iba't ibang hashCode, ang mga bagay ay ituturing na iba at ang katumbas na pamamaraan hindi man lang tatawagin.

"Sa aming halimbawa ng Fraction, kung ginawa namin ang hashCode na katumbas ng numerator, ang mga fraction na 2/3 at 4/6 ay magkakaroon ng magkaibang mga hashCode. Ang mga fraction ay pareho at ang equals method ay nagsasabing pareho sila, ngunit ang kanilang hashCodes ay nagsasabing magkaiba sila. At kung ihahambing natin ang paggamit ng hashCode bago natin ihambing ang paggamit ng mga katumbas, pagkatapos ay masasabi natin na ang mga bagay ay magkaiba at hindi man lang tayo nakarating sa paraang katumbas."

Narito ang isang halimbawa:

HashSet<Fraction>set = new HashSet<Fraction>();
set.add(new Fraction(2,3));System.out.println( set.contains(new Fraction(4,6)) );
Kung ang hashCode()  method ay nagbabalik ng mga fractions' numerator, ang resulta ay  false .
At ang bagay na «bagong Fraction(4,6) » ay hindi makikita sa koleksyon.

"Kaya ano ang tamang paraan upang ipatupad ang hashCode para sa mga fraction?"

"Dito kailangan mong tandaan na ang mga katumbas na fraction ay dapat magkaroon ng parehong hashCode."

" Bersyon 1 : ang hashCode ay katumbas ng resulta ng integer division."

"Para sa 7/5 at 6/5, ito ay magiging 1."

"Para sa 4/5 at 3/5, ito ay magiging 0."

"Ngunit ang pagpipiliang ito ay hindi angkop para sa paghahambing ng mga fraction na sadyang mas mababa sa 1. Ang hashCode (resulta ng integer division) ay palaging magiging 0."

" Bersyon 2 : ang hashCode ay katumbas ng resulta ng integer division ng denominator ng numerator."

"Ang pagpipiliang ito ay angkop para sa mga pagkakataon kung saan ang fraction ay mas mababa sa 1. Kung ang fraction ay mas mababa sa 1, kung gayon ang kabaligtaran nito ay mas malaki sa 1. At kung binaligtad natin ang lahat ng mga fraction, kung gayon ang mga paghahambing ay hindi maaapektuhan sa anumang paraan."

"Pinagsasama ng aming huling bersyon ang parehong mga solusyon:"

public int hashCode()
{
return numerator/denominator + denominator/numerator;
}

Subukan natin ito gamit ang 2/3 at 4/6. Dapat silang magkaroon ng magkaparehong mga hashCode:

Fraction 2/3 Fraction 4/6
numerator / denominador 2 / 3 == 0 4 / 6 == 0
denominador / numerator 3 / 2 == 1 6 / 4 == 1
numerator / denominator
+
denominator / numerator
0 + 1 == 1 0 + 1 == 1

"Yun lang muna."

"Salamat, Ellie. That was really interesting."