"अब मैं आपको कुछ ऐसे तरीकों के बारे में बताऊंगा जो उतने ही उपयोगी हैं:  बराबर(ऑब्जेक्ट ओ) और हैशकोड()। "

"आप शायद पहले ही याद कर चुके हैं कि, जावा में, संदर्भ चर की तुलना करते समय वस्तुओं की तुलना स्वयं नहीं की जाती है, बल्कि वस्तुओं के संदर्भों की तुलना की जाती है।"

कोड व्याख्या
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i==j);
i is not equal to j
चर विभिन्न वस्तुओं की ओर इशारा करते हैं।
भले ही वस्तुओं में समान डेटा हो।
Integer i = new Integer(1);
Integer j = i;
System.out.println(i==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)  यदि तुलना के लिए पास की गई वस्तु शून्य है , तो वस्तुएं समान नहीं हैं। यदि आप किसी वस्तु पर समान पद्धति को कॉल कर सकते हैं, तो यह निश्चित रूप से शून्य नहीं है ।"

" 2)  एक वर्ग तुलना। यदि वस्तुएं विभिन्न वर्गों के उदाहरण हैं, तो हम उनकी तुलना करने की कोशिश नहीं करेंगे। इसके बजाय, हम यह इंगित करने के लिए तुरंत वापसी का उपयोग करेंगे कि ये अलग-अलग वस्तुएं हैं।"

" 3)  दूसरी कक्षा से सभी को याद है कि 2/3 बराबर 4/6 है। लेकिन आप इसे कैसे चेक करते हैं?"

2/3 == 4/6
हम दोनों पक्षों को दोनों भाजकों (6 और 3) से गुणा करते हैं, और हमें मिलता है:
6*2==4*3
12 == 12
सामान्य नियम:
यदि
ए/बी == सी/डी
तो
ए * डी == सी * बी

"तदनुसार, बराबर विधि के तीसरे भाग में , हम पारित वस्तु को एक अंश में डालते हैं और भिन्नों की तुलना करते हैं।"

"समझ गया। अगर हम केवल अंश की तुलना अंश से और हर की तुलना हर से करें, तो 2/3 4/6 के बराबर नहीं है।"

"अब मैं समझता हूं कि आपका क्या मतलब था जब आपने कहा था कि केवल एक वर्ग का डेवलपर जानता है कि इसकी सही तुलना कैसे की जाए।"

"हाँ, लेकिन यह केवल आधी कहानी है।  एक और तरीका है: हैशकोड ()। "

"बराबर पद्धति के बारे में सब कुछ अब समझ में आता है, लेकिन हमें  हैशकोड () की आवश्यकता क्यों है? "

" हैशकोड विधि त्वरित तुलना के लिए आवश्यक है।"

" बराबर विधि का एक बड़ा नकारात्मक पहलू है: यह बहुत धीरे-धीरे काम करता है। मान लीजिए कि आपके पास लाखों तत्वों का एक सेट है और यह जांचने की आवश्यकता है कि इसमें कोई विशिष्ट वस्तु है या नहीं। आप यह कैसे करते हैं?"

"मैं लूप का उपयोग करके सभी तत्वों के माध्यम से साइकिल चला सकता हूं और सेट में प्रत्येक ऑब्जेक्ट के साथ ऑब्जेक्ट की तुलना कर सकता हूं। जब तक मुझे कोई मैच नहीं मिल जाता।"

"और अगर यह नहीं है? हम यह पता लगाने के लिए एक लाख तुलना करेंगे कि वस्तु वहाँ नहीं है? क्या यह बहुत अधिक नहीं लगता है?"

"हाँ, मैं भी मानता हूँ कि यह बहुत अधिक तुलना है। क्या कोई और तरीका है?"

"हाँ, आप इसके लिए हैशकोड () का उपयोग कर सकते हैं।

हैशकोड () विधि प्रत्येक वस्तु के लिए एक विशिष्ट संख्या लौटाती है एक वर्ग का डेवलपर यह तय करता है कि कौन सी संख्या लौटाई जाए, ठीक उसी तरह जैसे वह बराबर पद्धति के लिए करता है।

"आइए एक उदाहरण देखें:"

"कल्पना करें कि आपके पास दस लाख अंकों की संख्या है। फिर, आप संख्या को 100 से विभाजित करने के बाद प्रत्येक संख्या के हैशकोड को शेष बना सकते हैं।"

यहाँ एक उदाहरण है:

संख्या हमारा हैशकोड
1 2 3 4 5 6 7 8 9 0 90
9876554321 21
9876554221 21
9886554121 21

"हाँ, यह समझ में आता है। और हम इस हैशकोड के साथ क्या करते हैं?"

"संख्याओं की तुलना करने के बजाय, हम उनके हैशकोड्स की तुलना करते हैं । यह उस तरह से तेज़ है।"

"और हम बराबर को तभी कहते हैं जब उनके हैशकोड समान हों।"

"हाँ, यह तेज़ है। लेकिन हमें अभी भी एक लाख तुलना करनी है। हम केवल छोटी संख्याओं की तुलना कर रहे हैं, और हमें अभी भी हैशकोड से मेल खाने वाली किसी भी संख्या के बराबर कॉल करना है।"

"नहीं, आप बहुत कम संख्या में तुलना करके बच सकते हैं।"

"कल्पना करें कि हमारा सेट हैशकोड द्वारा समूहित या सॉर्ट किए गए नंबरों को स्टोर करता है (उन्हें इस तरह से सॉर्ट करना अनिवार्य रूप से उन्हें समूहीकृत करना है, क्योंकि समान हैशकोड वाले नंबर एक दूसरे के बगल में होंगे)। तब आप बहुत जल्दी और आसानी से अप्रासंगिक समूहों को हटा सकते हैं। यह पर्याप्त है। यह देखने के लिए प्रति समूह एक बार जांचें कि उसका हैशकोड ऑब्जेक्ट के हैशकोड से मेल खाता है या नहीं।"

"कल्पना कीजिए कि आप एक ऐसे दोस्त की तलाश में हैं जिसे आप देखकर पहचान सकते हैं और जिसे हम जानते हैं वह छात्रावास 17 में रहता है। फिर आप विश्वविद्यालय के हर छात्रावास में जाते हैं और पूछते हैं, 'क्या यह छात्रावास 17 है?' यदि ऐसा नहीं है, तो आप डॉर्म में सभी को अनदेखा करते हैं और अगले पर चले जाते हैं। यदि उत्तर 'हां' है, तो आप अपने मित्र की तलाश में प्रत्येक कमरे के पीछे चलना शुरू कर देते हैं।"

"इस उदाहरण में, डॉर्म नंबर (17) हैशकोड है।"

"एक हैशकोड फ़ंक्शन को लागू करने वाले डेवलपर को निम्नलिखित पता होना चाहिए:"

ए)  दो अलग-अलग वस्तुओं में एक ही हैशकोड हो सकता है  (अलग-अलग लोग एक ही छात्रावास में रह सकते हैं)

बी)  ऑब्जेक्ट्स जो समान हैं  ( बराबर विधि के अनुसारमें समान हैशकोड होना चाहिए। .

सी)  हैश कोड चुना जाना चाहिए ताकि एक ही हैशकोड के साथ कई अलग-अलग ऑब्जेक्ट न हों।  यदि हैं, तो हैशकोड के संभावित लाभ खो जाते हैं (आप डॉर्म 17 में जाते हैं और पाते हैं कि आधा विश्वविद्यालय वहां रहता है। बमर!)।

"और अब सबसे महत्वपूर्ण बात। यदि आप समान विधि को ओवरराइड करते हैं, तो आपको बिल्कुल हैशकोड () विधि को ओवरराइड करना चाहिए और ऊपर वर्णित तीन नियमों का पालन करना चाहिए।

"कारण यह है: जावा में, एक संग्रह में वस्तुओं की हमेशा हैशकोड () का उपयोग करके तुलना/पुनर्प्राप्ति की जाती है, इससे पहले कि वे समान का उपयोग करके तुलना/पुनर्प्राप्ति की जाती हैं।  और यदि समान वस्तुओं में अलग-अलग हैशकोड हैं, तो वस्तुओं को अलग और समान विधि माना जाएगा। नहीं बुलाया जाएगा।

"हमारे फ्रैक्शन उदाहरण में, यदि हम हैशकोड को अंश के बराबर बनाते हैं, तो भिन्न 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 अंश 4/6
अंश भाजक 2/3 == 0 4/6 == 0
भाजक / अंश 3/2 == 1 6/4 == 1
अंश / भाजक
+
भाजक / अंश
0 + 1 == 1 0 + 1 == 1

"अभी के लिए इतना ही।"

"धन्यवाद, ऐली। यह वास्तव में दिलचस्प था।"