1. जावा में वस्तुओं की तुलना करना
जावा में, वस्तुओं की तुलना संदर्भ और मूल्य दोनों से की जा सकती है।
संदर्भों की तुलना करना
यदि दो चर स्मृति में एक ही वस्तु की ओर इशारा करते हैं, तो इन चरों में संग्रहीत संदर्भ समान होते हैं। यदि आप समानता ऑपरेटर ( ==
) का उपयोग करके इन चरों की तुलना करते हैं, तो आप सही हो जाते हैं, और वह परिणाम समझ में आता है। यहाँ सब कुछ सरल है।
कोड | कंसोल आउटपुट |
---|---|
|
|
मूल्य से तुलना करना
लेकिन आप अक्सर ऐसी स्थितियों का सामना कर सकते हैं जहां दो चर दो अलग-अलग वस्तुओं को संदर्भित करते हैं जो समान हैं। उदाहरण के लिए, दो अलग-अलग स्ट्रिंग ऑब्जेक्ट जिनमें एक ही टेक्स्ट होता है।
यह निर्धारित करने के लिए कि विभिन्न वस्तुएं समान हैं या नहीं, equals()
विधि का उपयोग करें। उदाहरण के लिए:
कोड | कंसोल आउटपुट |
---|---|
|
|
विधि वर्ग equals
तक ही सीमित नहीं है String
। हर वर्ग के पास है।
यहाँ तक कि वे कक्षाएँ भी जो आप स्वयं लिखते हैं, और यहाँ क्यों है।
2. Object
वर्ग
जावा में सभी वर्ग Object
वर्ग को इनहेरिट करते हैं। जावा के निर्माता इस दृष्टिकोण के साथ आए।
और यदि कोई वर्ग वर्ग को इनहेरिट करता है , तो वह वर्ग Object
के सभी तरीकों को प्राप्त करता है । Object
और यह वंशानुक्रम का एक प्रमुख परिणाम है।
दूसरे शब्दों में, प्रत्येक वर्ग में कक्षा के तरीके होते हैं Object
, भले ही उनके कोड में उनका उल्लेख न हो।
इन विरासत में मिली विधियों में वस्तु तुलना से संबंधित विधियाँ शामिल हैं। ये हैं equals()
और hashCode()
तरीके।
कोड | वास्तव में, यहाँ हमारे पास क्या होगा: |
---|---|
|
|
ऊपर के उदाहरण में, हमने Person
नाम और उम्र के मापदंडों के साथ एक साधारण वर्ग बनाया, लेकिन एक भी तरीका नहीं। लेकिन क्योंकि सभी वर्ग Object
वर्ग को प्राप्त करते हैं, Person
वर्ग में स्वचालित रूप से दो विधियाँ होती हैं:
तरीका | विवरण |
---|---|
|
वर्तमान वस्तु और पारित वस्तु की तुलना करता है |
|
वर्तमान वस्तु का हैशकोड लौटाता है |
यह पता चला है कि बिल्कुल हर वस्तु की equals
विधि होती है, और विभिन्न प्रकार की वस्तुओं की एक दूसरे से तुलना की जा सकती है। ऐसा कोड संकलित और पूरी तरह से काम करेगा।
कोड | कंसोल आउटपुट |
---|---|
|
|
|
|
3. equals()
विधि
equals()
वर्ग से विरासत में मिली विधि , Object
वर्तमान वस्तु की पास की गई वस्तुओं से तुलना करने के लिए सबसे सरल एल्गोरिथ्म को लागू करती है: यह केवल वस्तुओं के संदर्भों की तुलना करती है।
यदि आप विधि को Person
कॉल करने के बजाय चर की तुलना करते हैं तो आपको वही परिणाम मिलता है । equals()
उदाहरण:
कोड | कंसोल आउटपुट |
---|---|
|
|
जब equals
विधि को चालू किया जाता है a
, तो यह केवल चर में संग्रहीत संदर्भ की तुलना चर a
में संग्रहीत संदर्भ से करता है।b
हालाँकि, तुलना String
कक्षा के लिए अलग तरह से काम करती है। क्यों?
क्योंकि कक्षा बनाने वाले लोगों ने विधि String
का अपना कार्यान्वयन लिखा था ।equals()
equals()
विधि का कार्यान्वयन
अब आइए Person
कक्षा में समान पद्धति के अपने कार्यान्वयन को लिखते हैं। हम 4 मुख्य मामलों पर विचार करेंगे।
equals
विधि को ओवरराइड करता हो, यह हमेशा एक Object
वस्तु को एक तर्क के रूप में लेता है
परिदृश्य 1 : वही वस्तु जिस पर equals
विधि कहलाती है, equals
विधि को भी पारित की जाती है। यदि वर्तमान वस्तु और पास की गई वस्तु के संदर्भ समान हैं, तो विधि को वापस आना चाहिए true
। एक वस्तु स्वयं के बराबर होती है।
कोड में यह ऐसा दिखाई देगा:
कोड | विवरण |
---|---|
|
संदर्भों की तुलना करें |
परिदृश्य 2 : विधि null
को पारित किया जाता है equals
- हमारे पास तुलना करने के लिए कुछ भी नहीं है। जिस वस्तु पर equals
विधि कहा जाता है वह निश्चित रूप से अशक्त नहीं है, इसलिए हमें false
इस मामले में वापस जाने की आवश्यकता है।
कोड में यह ऐसा दिखाई देगा:
कोड | विवरण |
---|---|
|
संदर्भों की तुलना करें पास की गई वस्तु है null ? |
परिदृश्य 3 : किसी ऑब्जेक्ट का संदर्भ जो विधि Person
में पास नहीं किया गया है। equals
क्या Person
वस्तु गैर- Person
वस्तु के बराबर है? यह वर्ग के विकासकर्ता के लिए एक प्रश्न है Person
कि वह कैसे चाहे या क्या चाहे।
लेकिन आमतौर पर वस्तुओं को समान माना जाने वाला एक ही वर्ग का होना चाहिए। इसलिए, अगर क्लास के ऑब्जेक्ट के अलावा कोई और चीज़ Person
हमारे बराबर मेथड में पास की जाती है, तो हम हमेशा वापस आ जाएंगे false
। आप किसी वस्तु के प्रकार की जांच कैसे कर सकते हैं? यह सही है — instanceof
ऑपरेटर का उपयोग करके।
यहाँ हमारा नया कोड कैसा दिखता है:
कोड | विवरण |
---|---|
|
संदर्भों की तुलना करें पास की गई वस्तु है null ? यदि पास की गई वस्तु a नहीं है Person |
4. दो Person
वस्तुओं की तुलना करना
हमने क्या किया? यदि हम विधि के अंत तक पहुँच चुके हैं, तो हमारे पास एक Person
वस्तु संदर्भ है जो नहीं है null
। इसलिए हम इसे एक में परिवर्तित करते हैं Person
और दोनों वस्तुओं के प्रासंगिक आंतरिक डेटा की तुलना करते हैं। और वह हमारा चौथा परिदृश्य है ।
कोड | विवरण |
---|---|
|
संदर्भों की तुलना करें पास की गई वस्तु है null ? यदि पास की गई वस्तु Person टाइपकास्टिंग नहीं है |
और आप दो Person
वस्तुओं की तुलना कैसे करते हैं? वे समान हैं यदि उनके नाम ( name
) और आयु ( age
) समान हैं। अंतिम कोड इस तरह दिखेगा:
कोड | विवरण |
---|---|
|
संदर्भों की तुलना करें पास की गई वस्तु है null ? यदि पास की गई वस्तु Person टाइपकास्टिंग नहीं है |
लेकिन वह सब नहीं है।
सबसे पहले, नाम फ़ील्ड एक है , इसलिए आपको विधि को String
कॉल करके नाम फ़ील्ड की तुलना करने की आवश्यकता है ।equals
this.name.equals(person.name)
दूसरा, name
क्षेत्र हो सकता है null
: उस स्थिति में, आप equals
उस पर कॉल नहीं कर सकते। आपको इसके लिए एक अतिरिक्त जांच की आवश्यकता है null
:
this.name != null && this.name.equals(person.name)
उस ने कहा, अगर नाम फ़ील्ड null
दोनों Person
वस्तुओं में है, तो नाम अभी भी बराबर हैं।
चौथे परिदृश्य के लिए कोड इस तरह दिख सकता है:
|
यदि आयु समान नहीं है, तत्काल return false यदि this.name के बराबर है null , तो equals विधि का उपयोग करके तुलना करने का कोई मतलब नहीं है। यहाँ या तो दूसरा name क्षेत्र के बराबर है null , या यह नहीं है। विधि का उपयोग करके दो नाम फ़ील्ड की तुलना करें । equals |
5. hashCode()
विधि
विधि के अलावा equals
, जिसका उद्देश्य दोनों वस्तुओं के सभी क्षेत्रों की विस्तृत तुलना करना है, एक और तरीका है जिसका उपयोग एक सटीक लेकिन बहुत तेज़ तुलना के लिए किया जा सकता है: hashCode()
.
कल्पना कीजिए कि आप वर्णानुक्रम में हजारों शब्दों की सूची को क्रमबद्ध कर रहे हैं, और आपको बार-बार शब्दों के जोड़े की तुलना करने की आवश्यकता है। और शब्द लंबे होते हैं, जिनमें बहुत सारे अक्षर होते हैं। सामान्यतया, इस तरह की तुलना में बहुत लंबा समय लगेगा।
लेकिन इसे तेज किया जा सकता है। मान लीजिए कि हमारे पास ऐसे शब्द हैं जो विभिन्न अक्षरों से शुरू होते हैं - यह तुरंत स्पष्ट हो जाता है कि वे भिन्न हैं। लेकिन अगर वे एक ही अक्षर से शुरू होते हैं, तो हम अभी यह नहीं कह सकते कि परिणाम क्या होगा: शब्द समान या भिन्न हो सकते हैं।
विधि hashCode()
एक समान सिद्धांत का उपयोग करके काम करती है। यदि आप इसे किसी वस्तु पर कॉल करते हैं, तो यह कुछ संख्या देता है - एक शब्द में पहले अक्षर के अनुरूप। इस संख्या के निम्नलिखित गुण हैं:
- समान वस्तुओं में हमेशा एक ही हैशकोड होता है
- अलग-अलग वस्तुओं में एक ही हैशकोड हो सकता है, या उनके हैशकोड अलग-अलग हो सकते हैं
- यदि वस्तुओं के अलग-अलग हैशकोड हैं, तो वस्तुएं निश्चित रूप से भिन्न हैं
इसे और भी स्पष्ट करने के लिए, आइए इन गुणों को शब्दों के संदर्भ में फिर से लिखें:
- समान शब्दों के पहले अक्षर हमेशा समान होते हैं।
- अलग-अलग शब्दों के पहले अक्षर एक जैसे हो सकते हैं, या उनके पहले अक्षर अलग-अलग हो सकते हैं
- यदि शब्दों के पहले अक्षर अलग हैं, तो शब्द निश्चित रूप से अलग हैं
वस्तुओं की तुलना में तेजी लाने के लिए अंतिम संपत्ति का उपयोग किया जाता है:
सबसे पहले, दो वस्तुओं के हैशकोड की गणना की जाती है। यदि ये हैशकोड अलग हैं, तो वस्तुएं निश्चित रूप से अलग हैं, और उनकी आगे तुलना करने की कोई आवश्यकता नहीं है।
लेकिन अगर हैशकोड समान हैं, तो हमें अभी भी समान पद्धति का उपयोग करके वस्तुओं की तुलना करनी होगी।
6. कोड में अनुबंध
ऊपर वर्णित व्यवहार जावा में सभी वर्गों द्वारा लागू किया जाना चाहिए। संकलन के दौरान, यह जांचने का कोई तरीका नहीं है कि वस्तुओं की तुलना सही ढंग से की गई है या नहीं।
जावा प्रोग्रामर के पास एक सार्वभौमिक समझौता है कि यदि वे बराबरी () पद्धति के अपने स्वयं के कार्यान्वयन को लिखते हैं और इस तरह मानक कार्यान्वयन (कक्षा में Object
) को ओवरराइड करते हैं, तो उन्हें hashCode()
विधि के अपने स्वयं के कार्यान्वयन को भी इस तरह से लिखना होगा कि उपरोक्त नियम हैं संतुष्ट।
इस व्यवस्था को अनुबंध कहा जाता है ।
यदि आप अपनी कक्षा में केवल equals()
या केवल hashCode()
पद्धति को लागू करते हैं, तो आप अनुबंध का घोर उल्लंघन कर रहे हैं (आपने अनुबंध तोड़ दिया है)। ऐसा मत करो।
यदि अन्य प्रोग्रामर आपके कोड का उपयोग करते हैं, तो यह ठीक से काम नहीं कर सकता है। और तो और, आप उस कोड का उपयोग करेंगे जो उपरोक्त अनुबंधों के पालन पर निर्भर करता है।
equals
किसी तत्व की खोज करते समय, सभी जावा संग्रह पहले वस्तुओं के हैशकोड की तुलना करते हैं, और उसके बाद ही विधि का उपयोग करके तुलना करते हैं।
इसका मतलब यह है कि यदि आप अपनी कक्षा को एक equals
विधि देते हैं लेकिन आप अपनी hashCode()
विधि नहीं लिखते हैं या आप इसे गलत तरीके से लागू करते हैं, तो हो सकता है कि संग्रह आपकी वस्तुओं के साथ सही ढंग से काम न करें।
उदाहरण के लिए, आप किसी सूची में कोई वस्तु जोड़ सकते हैं और फिर विधि का उपयोग करके उसे खोज सकते हैं contains()
, लेकिन संग्रह को आपकी वस्तु नहीं मिल सकती है।
GO TO FULL VERSION