CodeGym /Java Course /मॉड्यूल 2: Java Core /समान आणि हॅशकोड पद्धती: ते का आणि कुठे वापरायचे आणि ते कस...

समान आणि हॅशकोड पद्धती: ते का आणि कुठे वापरायचे आणि ते कसे कार्य करतात

मॉड्यूल 2: Java Core
पातळी 9 , धडा 1
उपलब्ध

"आता मी तुम्हाला काही पद्धतींबद्दल सांगेन ज्या सारख्याच उपयुक्त आहेत:  equals(Object o) & hashCode() ."

"तुम्ही कदाचित आधीच लक्षात ठेवले असेल की, Java मध्ये, संदर्भ व्हेरिएबल्सची तुलना करताना ऑब्जेक्ट्सची स्वतःची तुलना केली जात नाही, उलट ऑब्जेक्ट्सच्या संदर्भांशी."

कोड स्पष्टीकरण
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i==j);
i j च्या समान नाही
व्हेरिएबल्स वेगवेगळ्या ऑब्जेक्ट्सकडे निर्देश करतात.
जरी ऑब्जेक्ट्समध्ये समान डेटा असतो.
Integer i = new Integer(1);
Integer j = i;
System.out.println(i==j);
मी j बरोबर आहे. व्हेरिएबल्समध्ये समान ऑब्जेक्टचा संदर्भ असतो.

"हो, मला ते आठवतंय."

बरोबरी  आहे .

"इक्वल मेथड हे येथे प्रमाणित उपाय आहे. इक्वल्स पद्धतीचा उद्देश वस्तूंच्या आत साठवलेल्या गोष्टींची तुलना करून आंतरिकरित्या एकसारखे आहेत की नाही हे निर्धारित करणे आहे."

"आणि ते कसे करते?"

"हे सर्व toString() पद्धतीसारखेच आहे."

ऑब्जेक्ट क्लासमध्ये समान पद्धतीची स्वतःची अंमलबजावणी आहे, जी फक्त संदर्भांची तुलना करते:

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

"छान... पुन्हा त्याकडे परत आलो आहोत ना?"

"तुमची हनुवटी वर ठेवा! खरं तर खूप अवघड आहे."

"ही पद्धत विकसकांना त्यांच्या स्वतःच्या वर्गांमध्ये अधिलिखित करण्यास अनुमती देण्यासाठी तयार करण्यात आली होती. शेवटी, तुलना करताना कोणता डेटा संबंधित आहे आणि कोणता नाही हे केवळ वर्गाच्या विकासकालाच माहीत असते."

"तुम्ही एक उदाहरण देऊ शकता?"

"नक्की. समजा आपल्याकडे गणितीय अपूर्णांकांचे प्रतिनिधित्व करणारा वर्ग आहे. तो असे दिसेल:"

उदाहरण:
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;
}
}
उदाहरण पद्धत कॉल:
Fraction one = new Fraction(2,3);
Fraction two = new Fraction(4,6);
System.out.println(one.equals(two));
पद्धत कॉल सत्य परत येईल.
अपूर्णांक 2/3 हा अपूर्णांक 4/6 च्या बरोबरीचा आहे

"आता, या उदाहरणाचे विच्छेदन करूया."

"आम्ही समान पद्धत ओव्हररॉड केली आहे, त्यामुळे फ्रॅक्शन ऑब्जेक्ट्सची स्वतःची अंमलबजावणी होईल.

"पद्धतीमध्ये अनेक तपासण्या आहेत:"

" 1)  जर तुलनेसाठी पास केलेला ऑब्जेक्ट null असेल , तर ऑब्जेक्ट्स समान नसतील. जर तुम्ही एखाद्या ऑब्जेक्टवर equals पद्धत म्हणू शकत असाल, तर ती नक्कीच शून्य नाही ."

" 2)  एक वर्ग तुलना. जर वस्तू वेगवेगळ्या वर्गांची उदाहरणे असतील, तर आम्ही त्यांची तुलना करण्याचा प्रयत्न करणार नाही. त्याऐवजी, आम्ही लगेचच रिटर्न फॉल्सचा वापर करू हे सूचित करण्यासाठी की या भिन्न वस्तू आहेत."

" 3)  दुसऱ्या इयत्तेपासून प्रत्येकाला आठवते की 2/3 म्हणजे 4/6. पण तुम्ही ते कसे तपासाल?"

२/३ == ४/६
आम्ही दोन्ही बाजूंना दोन्ही विभाजकांनी गुणाकार करतो (6 आणि 3), आणि आम्हाला मिळते:
6 * 2 == 4 * 3
१२ == १२
सामान्य नियम:
जर
a / b == c / d
तर
a * d == c * b

"त्यानुसार, समान पद्धतीच्या तिसर्‍या भागात , आम्ही पास केलेल्या ऑब्जेक्टला अपूर्णांकावर टाकतो आणि अपूर्णांकांची तुलना करतो."

"समजले. जर आपण फक्त अंशाची अंशाशी आणि भाजकाची भाजकाशी तुलना केली, तर 2/3 4/6 बरोबर नाही."

"आता मला समजले की तुमचा अर्थ काय होता हे तुम्ही म्हटल्यावर फक्त वर्गाच्या विकसकाला त्याची योग्यरित्या तुलना कशी करायची हे माहित आहे."

"होय, पण ती फक्त अर्धी कथा आहे.  दुसरी पद्धत आहे: हॅशकोड() .

"समान पद्धतीबद्दल सर्व काही आता अर्थपूर्ण आहे, परंतु आम्हाला  हॅशकोड () ची आवश्यकता का आहे? "

" त्वरित तुलना करण्यासाठी हॅशकोड पद्धत आवश्यक आहे."

" इक्वल पद्धतीची एक मोठी कमतरता आहे: ती खूप हळू चालते. समजा तुमच्याकडे लाखो घटकांचा संच आहे आणि त्यात विशिष्ट वस्तू आहे की नाही हे तपासण्याची गरज आहे. तुम्ही ते कसे कराल?"

"मी लूप वापरून सर्व घटकांद्वारे सायकल करू शकतो आणि सेटमधील प्रत्येक ऑब्जेक्टशी ऑब्जेक्टची तुलना करू शकतो. जोपर्यंत मला एक जुळणी सापडत नाही."

"आणि ती तिथे नसेल तर? ती वस्तू तिथे नाही हे शोधण्यासाठी आम्ही एक दशलक्ष तुलना करू? खूप काही वाटत नाही का?"

"हो, मी ओळखतो की ही खूप तुलना आहे. दुसरा मार्ग आहे का?"

"होय, तुम्ही यासाठी हॅशकोड () वापरू शकता .

हॅशकोड ( ) पद्धत प्रत्येक ऑब्जेक्टसाठी विशिष्ट क्रमांक मिळवते. वर्गाचा विकसक ठरवतो की कोणती संख्या परत केली जाते, जसे तो किंवा ती समान पद्धतीसाठी करतो.

"चला एक उदाहरण पाहू:"

"कल्पना करा की तुमच्याकडे एक दशलक्ष 10-अंकी संख्या आहेत. त्यानंतर, तुम्ही प्रत्येक संख्येचा हॅशकोड 100 ने भाग केल्यावर उर्वरित बनवू शकता."

येथे एक उदाहरण आहे:

क्रमांक आमचा हॅशकोड
१२३४५६७८९० 90
९८७६५५४३२१ २१
९८७६५५४२२१ २१
९८८६५५४१२१ २१

"हो, याचा अर्थ आहे. आणि आम्ही या हॅशकोडचे काय करू?"

"संख्यांची तुलना करण्याऐवजी, आम्ही त्यांच्या हॅशकोड्सची तुलना करतो . हे त्या मार्गाने जलद आहे."

"आणि जर त्यांचे हॅशकोड समान असतील तरच आम्ही समतुल्य म्हणतो."

"हो, ते जलद आहे. पण तरीही आम्हाला दहा लाख तुलना कराव्या लागतील. आम्ही फक्त लहान संख्यांची तुलना करत आहोत, आणि आम्हाला अजूनही हॅशकोडशी जुळणार्‍या कोणत्याही संख्येसाठी बरोबरी म्हणावी लागेल."

"नाही, तुम्ही खूप कमी संख्येने तुलना करून दूर जाऊ शकता."

"कल्पना करा की आमचा संच हॅशकोड द्वारे गटबद्ध किंवा क्रमवारी लावलेला क्रमांक संग्रहित करतो (अशा प्रकारे क्रमवारी लावणे मूलत: त्यांचे गटबद्ध करणे आहे, कारण समान हॅशकोड असलेले क्रमांक एकमेकांच्या पुढे असतील). मग तुम्ही अप्रासंगिक गट फार लवकर आणि सहजपणे टाकून देऊ शकता. ते पुरेसे आहे. त्याचा हॅशकोड ऑब्जेक्टच्या हॅशकोडशी जुळतो की नाही हे पाहण्यासाठी प्रत्येक गटात एकदा तपासण्यासाठी.

"कल्पना करा की तुम्ही विद्यार्थी असा मित्र शोधत आहात ज्याला तुम्ही नजरेने ओळखू शकता आणि ज्याला आपण डॉर्म 17 मध्ये राहतो हे आपण ओळखतो. मग तुम्ही विद्यापीठातील प्रत्येक वसतिगृहात जा आणि विचारा, 'हे डॉर्म 17 आहे का?' जर तसे नसेल, तर तुम्ही वसतिगृहातील प्रत्येकाकडे दुर्लक्ष करून पुढच्या ठिकाणी जा. जर उत्तर 'होय' असेल, तर तुम्ही तुमच्या मित्राचा शोध घेत प्रत्येक खोलीच्या मागे फिरू लागाल."

"या उदाहरणात, डॉर्म नंबर (17) हा हॅशकोड आहे."

"हॅशकोड फंक्शन लागू करणार्‍या विकसकाला खालील माहिती असणे आवश्यक आहे:"

अ)  दोन भिन्न वस्तूंमध्ये समान हॅशकोड असू शकतो  (वेगवेगळे लोक एकाच वसतिगृहात राहू शकतात)

ब)  समान असलेल्या वस्तूंकडे  ( समान पद्धतीनुसारसमान हॅशकोड असणे आवश्यक आहे. .

C)  हॅश कोड निवडणे आवश्यक आहे जेणेकरून एकाच हॅशकोडसह बरेच भिन्न ऑब्जेक्ट्स नसतील.  तेथे असल्यास, हॅशकोड्सचे संभाव्य फायदे गमावले आहेत (तुम्ही डॉर्म 17 वर जा आणि तेथे अर्धे विद्यापीठ राहत असल्याचे आढळले. बमर!).

"आणि आता सर्वात महत्वाची गोष्ट. जर तुम्ही equals पद्धत ओव्हरराइड केली, तर तुम्ही हॅशकोड () पद्धत पूर्णपणे ओव्हरराइड केली पाहिजे आणि वर वर्णन केलेल्या तीन नियमांचे पालन केले पाहिजे.

"कारण हे आहे: जावामध्ये, संग्रहातील वस्तूंची तुलना/मिळवण्याआधी हॅशकोड() वापरून तुलना केली जाते/पुनर्प्राप्त केली जाते.  आणि जर एकसारख्या वस्तूंचे हॅशकोड वेगळे असतील, तर वस्तू वेगळ्या मानल्या जातील आणि समान पद्धत. बोलावलेही जाणार नाही.

"आमच्या अपूर्णांकाच्या उदाहरणात, जर आपण हॅशकोडला अंशाच्या समान केले तर, 2/3 आणि 4/6 या अपूर्णांकांना भिन्न हॅशकोड असतील. अपूर्णांक समान आहेत आणि समान पद्धत सांगते की ते समान आहेत, परंतु त्यांचे हॅशकोड म्हणतात ते भिन्न आहेत. आणि जर आपण समान वापरून तुलना करण्यापूर्वी हॅशकोड वापरून तुलना केली, तर आपण असा निष्कर्ष काढू शकतो की ऑब्जेक्ट्स भिन्न आहेत आणि आपण ते कधीही समान पद्धतीपर्यंत पोहोचत नाही."

येथे एक उदाहरण आहे:

HashSet<Fraction>set = new HashSet<Fraction>();
set.add(new Fraction(2,3));System.out.println( set.contains(new Fraction(4,6)) );
जर हॅशकोड()  पद्धतीने अपूर्णांकांचे अंश परत केले, तर निकाल  चुकीचा असेल . आणि संग्रहात
"नवीन अपूर्णांक(4,6) " ऑब्जेक्ट सापडणार नाही.

"तर अपूर्णांकांसाठी हॅशकोड लागू करण्याचा योग्य मार्ग कोणता आहे?"

"येथे तुम्हाला हे लक्षात ठेवणे आवश्यक आहे की समतुल्य अपूर्णांकांमध्ये समान हॅशकोड असणे आवश्यक आहे."

" आवृत्ती 1 : हॅशकोड पूर्णांक भागाकाराच्या परिणामाप्रमाणे आहे."

"7/5 आणि 6/5 साठी, हे 1 असेल."

"4/5 आणि 3/5 साठी, हे 0 असेल."

"परंतु मुद्दाम 1 पेक्षा कमी असलेल्या अपूर्णांकांची तुलना करण्यासाठी हा पर्याय योग्य नाही. हॅशकोड (पूर्णांक विभागणीचा परिणाम) नेहमी 0 असेल."

" आवृत्ती 2 : हॅशकोड अंशाने भाजकाच्या पूर्णांक भागाकाराच्या परिणामाप्रमाणे आहे."

"हा पर्याय अशा उदाहरणांसाठी योग्य आहे जिथे अपूर्णांक 1 पेक्षा कमी आहे. जर अपूर्णांक 1 पेक्षा कमी असेल, तर त्याचा व्यस्त 1 पेक्षा मोठा असेल. आणि जर आपण सर्व अपूर्णांक उलटे केले, तर तुलनांवर कोणत्याही प्रकारे परिणाम होणार नाही."

"आमची अंतिम आवृत्ती दोन्ही उपाय एकत्र करते:"

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

2/3 आणि 4/6 वापरून त्याची चाचणी करू. त्यांच्याकडे एकसारखे हॅशकोड असावेत:

अपूर्णांक 2/3 अपूर्णांक ४/६
अंश / भाजक 2 / 3 == 0 ४/६ == ०
भाजक / अंश ३/२ == १ ६/४ == १
अंश / भाजक
+
भाजक / अंश
0 + 1 == 1 0 + 1 == 1

"सध्या एवढेच."

"धन्यवाद, एली. ते खरोखरच मनोरंजक होते."

टिप्पण्या
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION