1. Java मधील वस्तूंची तुलना करणे

Java मध्ये, वस्तूंची तुलना संदर्भ आणि मूल्यानुसार केली जाऊ शकते.

संदर्भांची तुलना

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

कोड कन्सोल आउटपुट
Integer a = 5;
Integer b = a;
System.out.println(a == b);


true

मूल्यानुसार तुलना करणे

परंतु आपण अनेकदा अशा परिस्थितींना सामोरे जाऊ शकता जिथे दोन व्हेरिएबल्स एकसारख्या दोन भिन्न वस्तूंचा संदर्भ देतात. उदाहरणार्थ, दोन भिन्न स्ट्रिंग ऑब्जेक्ट्स ज्यात समान मजकूर आहे.

भिन्न वस्तू एकसारख्या आहेत की नाही हे निर्धारित करण्यासाठी, equals()पद्धत वापरा. उदाहरणार्थ:

कोड कन्सोल आउटपुट
String a = new String("Hello");
String b = new String("Hello");
System.out.println(a == b);
System.out.println(a.equals(b));


false
true

पद्धत equalsवर्गापुरती मर्यादित नाही String. प्रत्येक वर्गाकडे आहे.

तुम्ही स्वत: लिहिता असे वर्ग देखील, आणि याचे कारण येथे आहे.



2. Objectवर्ग

Java मधील सर्व वर्गांना Objectवर्गाचा वारसा मिळतो. जावाच्या निर्मात्यांनी हा दृष्टिकोन शोधून काढला.

आणि जर एखाद्या वर्गाला Objectवर्गाचा वारसा मिळाला तर तो वर्गाच्या सर्व पद्धती मिळवतो Object. आणि हा वारसाहक्काचा एक मोठा परिणाम आहे.

दुसऱ्या शब्दांत, प्रत्येक वर्गाकडे वर्गाच्या पद्धती असतात Object, जरी त्यांच्या कोडमध्ये त्यांचा उल्लेख नसला तरीही.

या वारशाने मिळालेल्या पद्धतींमध्ये ऑब्जेक्ट तुलनाशी संबंधित पद्धतींचा समावेश होतो. या equals()आणि hashCode()पद्धती आहेत.

कोड प्रत्यक्षात, आमच्याकडे काय असेल ते येथे आहे:
class Person
{
   String name;
   int age;
}
class Person extends Object
{
   String name;
   int age;

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

   public int hashCode()
   {
      return address_of_object_in_memory; // This is the default implementation, but there may be a different implementation
   }
}

वरील उदाहरणामध्ये, आम्ही Personनाव आणि वय पॅरामीटर्ससह एक साधा वर्ग तयार केला आहे, परंतु एकच पद्धत नाही. परंतु सर्व वर्गांना Objectवर्गाचा वारसा मिळत असल्याने, Personवर्गात आपोआप दोन पद्धती आहेत:

पद्धत वर्णन
boolean equals(Object obj)
वर्तमान ऑब्जेक्ट आणि पास केलेल्या ऑब्जेक्टची तुलना करते
int hashCode()
वर्तमान ऑब्जेक्टचा हॅशकोड परत करतो

असे दिसून आले की पूर्णपणे प्रत्येक वस्तूची equalsपद्धत असते आणि वेगवेगळ्या प्रकारच्या वस्तूंची एकमेकांशी तुलना केली जाऊ शकते. असा कोड संकलित करेल आणि उत्तम प्रकारे कार्य करेल.

कोड कन्सोल आउटपुट
Integer a = 5;
String s = "Hello";
System.out.println(a.equals(s));
System.out.println(s.equals(a));


false
false
Object a = new Integer(5);
Object b = new Integer(5);
System.out.println(a.equals(b)) ;


true

3. equals()पद्धत

equals()क्लासमधून वारसा मिळालेली पद्धत , Objectवर्तमान ऑब्जेक्टची उत्तीर्ण वस्तूंशी तुलना करण्यासाठी सर्वात सोपा अल्गोरिदम लागू करते: ती फक्त ऑब्जेक्ट्सच्या संदर्भांची तुलना करते.

Personजर तुम्ही पद्धत कॉल करण्याऐवजी व्हेरिएबल्सची तुलना केली तर तुम्हाला समान परिणाम मिळेल equals(). उदाहरण:

कोड कन्सोल आउटपुट
Person a = new Person();
a.name = "Steve";

Person b = new Person();
b.name = "Steve";

System.out.println(a == b);
System.out.println(a.equals(b));






false
false

जेव्हा equalsपद्धत ऑन केली जाते a, तेव्हा ते व्हेरिएबलमध्ये संग्रहित केलेल्या संदर्भाची aव्हेरिएबलमध्ये संचयित केलेल्या संदर्भाशी तुलना करते b.

तथापि, वर्गासाठी तुलना वेगळ्या पद्धतीने कार्य करते String. का?

कारण वर्ग तयार करणार्‍यांनी Stringस्वतःच्या पद्धतीची अंमलबजावणी लिहिली equals().

equals()पद्धतीची अंमलबजावणी

आता वर्गात समान पद्धतीची स्वतःची अंमलबजावणी लिहू Person. आम्ही 4 मुख्य प्रकरणांचा विचार करू.

महत्वाचे:
कोणता वर्ग equalsपद्धत ओव्हरराइड करतो याची पर्वा न करता, ते नेहमी एखाद्या Objectवस्तूला युक्तिवाद म्हणून घेते

परिस्थिती 1 : ज्या ऑब्जेक्टवर मेथड equalsकॉल केली जाते तीच ऑब्जेक्ट मेथडला देखील दिली जाते equals. वर्तमान ऑब्जेक्ट आणि पास केलेल्या ऑब्जेक्टचे संदर्भ समान असल्यास, पद्धत परत येणे आवश्यक आहे true. एखादी वस्तू स्वतः सारखी असते.

कोडमध्ये ते असे दिसेल:

कोड वर्णन
public boolean equals(Object obj)
{
   if (this == obj)
    return true;

   // The rest of the code of the equals method
}


संदर्भांची तुलना करा

परिस्थिती 2 : nullपद्धतीकडे पाठवले जाते equals- आमच्याकडे तुलना करण्यासाठी काहीही नाही. ज्या ऑब्जेक्टवर पद्धत कॉल केली जाते ती निश्चितपणे शून्य नाही, म्हणून आपल्याला या प्रकरणात equalsपरत येणे आवश्यक आहे .false

कोडमध्ये ते असे दिसेल:

कोड वर्णन
public boolean equals(Object obj)
{
   if (this == obj)
      return true;

   if (obj == null)
      return false;

   // The rest of the code of the equals method
}


संदर्भांची तुलना करा


पास केलेली वस्तू आहे का null?

परिस्थिती 3 : एक नसलेल्या ऑब्जेक्टचा संदर्भ Personपद्धतीकडे पाठवला जातो equals. Personवस्तू नॉन-ऑब्जेक्ट सारखी आहे का Person? वर्गाच्या विकासकाने Personत्याला किंवा तिला हवे तसे ठरवायचे हा प्रश्न आहे.

परंतु सामान्यतः समान समजण्यासाठी वस्तू समान वर्गाच्या असणे आवश्यक आहे. म्हणून, जर वर्गातील ऑब्जेक्ट व्यतिरिक्त काहीतरी Personआमच्या समान पद्धतीमध्ये पास केले गेले, तर आम्ही नेहमी परत येऊ false. तुम्ही एखाद्या वस्तूचा प्रकार कसा तपासू शकता? ते बरोबर आहे — ऑपरेटर वापरून instanceof.

आमचा नवीन कोड कसा दिसतो ते येथे आहे:

कोड वर्णन
public boolean equals(Object obj)
{
   if (this == obj)
      return true;

   if (obj == null)
      return false;

   if (!(obj instanceof Person))
      return false;

   // The rest of the code of the equals method
}


संदर्भांची तुलना करा


पास केलेली वस्तू आहे का null?


उत्तीर्ण वस्तू नसल्यास अPerson

4. दोन Personवस्तूंची तुलना करणे

आम्ही काय संपले? जर आपण पद्धतीच्या शेवटी पोहोचलो, तर आपल्याकडे Personऑब्जेक्ट संदर्भ आहे जो नाही null. म्हणून आम्ही ते a मध्ये रूपांतरित करतो Personआणि दोन्ही ऑब्जेक्ट्सच्या संबंधित अंतर्गत डेटाची तुलना करतो. आणि ही आमची चौथी परिस्थिती आहे .

कोड वर्णन
public boolean equals(Object obj)
{
   if (this == obj)
      return true;

   if (obj == null)
      return false;

   if (!(obj instanceof Person))
      return false;

   Person person = (Person) obj;

   // The rest of the code of the equals method
}


संदर्भांची तुलना करा


पास केलेली वस्तू आहे का null? पास केलेली ऑब्जेक्ट टायपकास्टिंग


नसल्यासPerson


आणि तुम्ही दोन वस्तूंची तुलना कशी कराल Person? त्यांचे नाव ( name) आणि वय ( age) समान असल्यास ते समान आहेत. अंतिम कोड असे दिसेल:

कोड वर्णन
public boolean equals(Object obj)
{
   if (this == obj)
      return true;

   if (obj == null)
      return false;

   if (!(obj instanceof Person))
      return false;

   Person person = (Person) obj;

   return this.name == person.name && this.age == person.age;
}


संदर्भांची तुलना करा


पास केलेली वस्तू आहे का null? पास केलेली ऑब्जेक्ट टायपकास्टिंग


नसल्यासPerson


पण एवढेच नाही.

प्रथम, नाव फील्ड a आहे String, म्हणून तुम्हाला पद्धत कॉल करून नाव फील्डची तुलना करणे आवश्यक आहे equals.

this.name.equals(person.name)

दुसरे, nameफील्ड असू शकते null: त्या बाबतीत, आपण equalsत्यावर कॉल करू शकत नाही. आपल्याला यासाठी अतिरिक्त तपासणी आवश्यक आहे null:

this.name != null && this.name.equals(person.name)

ते म्हणाले, जर नाव फील्ड nullदोन्ही Personवस्तूंमध्ये असेल, तर नावे अद्याप समान आहेत.

चौथ्या परिस्थितीचा कोड कदाचित यासारखा दिसू शकेल:

Person person = (Person) obj;

if (this.age != person.age)
   return false;

if (this.name == null)
   return person.name == null;

return this.name.equals(person.name);


वयोगट समान नसल्यास,
लगेच return false

जर this.nameसमान असेल तर null, पद्धत वापरून तुलना करण्यात काही अर्थ नाही equals. येथे एकतर दुसरे nameफील्ड समान आहे nullकिंवा ते नाही.

पद्धत वापरून दोन नाव फील्डची तुलना करा equals.


5. hashCode()पद्धत

equalsदोन्ही ऑब्जेक्ट्सच्या सर्व फील्डची तपशीलवार तुलना करण्याच्या उद्देशाने असलेल्या पद्धतीव्यतिरिक्त, आणखी एक पद्धत आहे जी अस्पष्ट परंतु अतिशय द्रुत तुलनासाठी वापरली जाऊ शकते : hashCode().

कल्पना करा की तुम्ही अक्षरानुसार हजारो शब्दांची सूची क्रमवारी लावत आहात आणि तुम्हाला शब्दांच्या जोडीची वारंवार तुलना करावी लागेल. आणि शब्द लांब आहेत, त्यात बरीच अक्षरे आहेत. सर्वसाधारणपणे, अशी तुलना खूप वेळ घेईल.

पण वेग वाढवता येतो. समजा आपल्याकडे वेगवेगळ्या अक्षरांनी सुरू होणारे शब्द आहेत - ते वेगळे आहेत हे लगेच स्पष्ट होते. परंतु जर ते समान अक्षरांनी सुरू झाले, तर परिणाम काय होईल हे आम्ही अद्याप सांगू शकत नाही: शब्द समान किंवा भिन्न असू शकतात.

पद्धत hashCode()समान तत्त्व वापरून कार्य करते. आपण एखाद्या वस्तूवर कॉल केल्यास, ते काही संख्या परत करते - शब्दातील पहिल्या अक्षराप्रमाणे. या नंबरमध्ये खालील गुणधर्म आहेत:

  • समान वस्तूंमध्ये नेहमी समान हॅशकोड असतो
  • वेगवेगळ्या ऑब्जेक्ट्समध्ये समान हॅशकोड असू शकतात किंवा त्यांचे हॅशकोड वेगळे असू शकतात
  • जर ऑब्जेक्ट्समध्ये भिन्न हॅशकोड असतील, तर ऑब्जेक्ट्स नक्कीच भिन्न आहेत

हे आणखी स्पष्ट करण्‍यासाठी, या गुणधर्मांना शब्दांमध्‍ये रीफ्रेम करूया:

  • समान शब्दांमध्ये नेहमी समान प्रथम अक्षरे असतात.
  • वेगवेगळ्या शब्दांची पहिली अक्षरे समान असू शकतात किंवा त्यांची पहिली अक्षरे वेगळी असू शकतात
  • जर शब्दांची पहिली अक्षरे वेगळी असतील तर शब्द नक्कीच वेगळे असतील

वस्तूंची तुलना वेगवान करण्यासाठी शेवटची मालमत्ता वापरली जाते:

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

परंतु जर हॅशकोड समान असतील, तर आपल्याला समान पद्धती वापरून ऑब्जेक्ट्सची तुलना करावी लागेल.



6. कोडमधील करार

वर वर्णन केलेले वर्तन Java मधील सर्व वर्गांनी लागू केले पाहिजे. संकलनादरम्यान, वस्तूंची तुलना योग्य प्रकारे केली जाते की नाही हे तपासण्याचा कोणताही मार्ग नाही.

Java प्रोग्रामरचा एक सार्वत्रिक करार आहे की जर त्यांनी समान() पद्धतीची स्वतःची अंमलबजावणी लिहिली आणि त्याद्वारे मानक अंमलबजावणी (वर्गात Object) ओव्हरराइड केली, तर त्यांनी स्वतःच्या पद्धतीची अंमलबजावणी hashCode()अशा प्रकारे लिहिली पाहिजे की वरील नियम समाधानी

या व्यवस्थेला करार म्हणतात .

तुम्ही तुमच्या वर्गात फक्त equals()किंवा फक्त hashCode()पद्धत अंमलात आणल्यास, तुम्ही कराराचे घोर उल्लंघन करत आहात (तुम्ही करार मोडला आहे). हे करू नका.

इतर प्रोग्रामर तुमचा कोड वापरत असल्यास, ते योग्यरित्या कार्य करणार नाही. इतकेच काय, तुम्ही वरील करारांच्या पालनावर अवलंबून असलेला कोड वापराल.

महत्वाचे!

घटक शोधताना, सर्व Java संग्रह प्रथम ऑब्जेक्ट्सच्या हॅशकोडची तुलना करतात आणि त्यानंतरच equalsपद्धत वापरून तुलना करतात.

याचा अर्थ असा की जर तुम्ही तुमच्या स्वतःच्या वर्गाला एक पद्धत दिली परंतु तुम्ही तुमची स्वतःची पद्धत equalsलिहिली नाही किंवा तुम्ही ती चुकीच्या पद्धतीने अंमलात आणली, तर संग्रह तुमच्या ऑब्जेक्ट्ससह योग्यरित्या कार्य करू शकत नाहीत.hashCode()

उदाहरणार्थ, तुम्ही सूचीमध्ये एखादी वस्तू जोडू शकता आणि नंतर ती contains()पद्धत वापरून शोधू शकता, परंतु संग्रहाला तुमचा ऑब्जेक्ट सापडणार नाही.