जावा में बराबरी और हैशकोड को देखते समय किन मुद्दों पर विचार किया जाना चाहिए?


617

ओवरराइड करते समय equalsऔर किन मुद्दों पर विचार किया जाना चाहिए hashCode?

जवाबों:


1439

सिद्धांत (भाषा के वकीलों और गणितीय रूप से इच्छुक):

equals()( javadoc ) को एक समतुल्य संबंध को परिभाषित करना चाहिए (यह प्रतिवर्त , सममित और परिवर्तनशील होना चाहिए )। इसके अलावा, यह सुसंगत होना चाहिए (यदि वस्तुओं को संशोधित नहीं किया गया है, तो इसे उसी मूल्य पर वापस रखना होगा)। इसके अलावा, o.equals(null)हमेशा झूठी वापसी करनी चाहिए।

hashCode()( javadoc ) भी सुसंगत होना चाहिए (यदि वस्तु को संदर्भ में संशोधित नहीं किया गया है equals(), तो उसे उसी मान को लौटाते रहना चाहिए)।

संबंध दो तरीकों के बीच है:

जब भी a.equals(b), तब a.hashCode()जैसा होना चाहिए b.hashCode()

प्रयोग में:

यदि आप एक को ओवरराइड करते हैं, तो आपको दूसरे को ओवरराइड करना चाहिए।

खेतों के उसी सेट का उपयोग करें जिसका उपयोग आप गणना करने के लिए करते हैं equals() लिएhashCode()

अपाचे कॉमन्स लैंग लाइब्रेरी से उत्कृष्ट हेल्पर क्लास इक्वाल्सबर्ल और हैशकोडब्यूरीट का उपयोग करें । एक उदाहरण:

public class Person {
    private String name;
    private int age;
    // ...

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers
            // if deriving: appendSuper(super.hashCode()).
            append(name).
            append(age).
            toHashCode();
    }

    @Override
    public boolean equals(Object obj) {
       if (!(obj instanceof Person))
            return false;
        if (obj == this)
            return true;

        Person rhs = (Person) obj;
        return new EqualsBuilder().
            // if deriving: appendSuper(super.equals(obj)).
            append(name, rhs.name).
            append(age, rhs.age).
            isEquals();
    }
}

यह भी याद रखें:

जब का उपयोग कर एक हैश आधारित संग्रह या मानचित्र जैसे HashSet , LinkedHashSet , HashMap , Hashtable , या WeakHashMap , सुनिश्चित करें कि hashCode () कुंजी वस्तुओं की है कि आप संग्रह में कभी नहीं डाल जबकि वस्तु संग्रह में है परिवर्तन करें। यह सुनिश्चित करने का बुलेटप्रूफ तरीका आपकी चाबी को अपरिवर्तनीय बनाना है, जिसके अन्य लाभ भी हैं


12
परिशिष्ट के बारे में अतिरिक्त बिंदु (): आपको इसका उपयोग हैशकोड () और बराबर () में करना चाहिए और यदि आप केवल सुपरक्लास के समानता व्यवहार को प्राप्त करना चाहते हैं। उदाहरण के लिए, यदि आप ऑब्जेक्ट से सीधे प्राप्त करते हैं, तो कोई मतलब नहीं है क्योंकि सभी ऑब्जेक्ट डिफ़ॉल्ट रूप से अलग हैं।
अंटी Kissaniemi

312
आपके लिए दो विधियाँ उत्पन्न करने के लिए आप ग्रहण पा सकते हैं: स्रोत> हैशकोड () और समान () उत्पन्न करें।
रोक स्ट्रनिसा

27
Netbeans के साथ भी यही सच है: developmentality.wordpress.com/2010/08/24/…
seinecle

6
@Darthenius ग्रहण जनित समतुल्यता getClass () का उपयोग करती है जिसके कारण कुछ मामलों में समस्या हो सकती है (प्रभावी जावा आइटम देखें 8)
AndroidGecko

7
पहली अशक्तता की जांच इस तथ्य को देखते हुए आवश्यक नहीं है कि instanceofयदि इसका पहला ऑपरेंड शून्य है (तो प्रभावी जावा फिर से)।
izaban

295

यदि आप उन कक्षाओं के साथ व्यवहार कर रहे हैं जो हाइबरनेट की तरह एक ऑब्जेक्ट-रिलेशनशिप मैपर (ORM) का उपयोग कर रहे हैं, तो ध्यान देने योग्य कुछ मुद्दे हैं, अगर आपको नहीं लगता कि यह अनुचित रूप से पहले से ही जटिल था!

आलसी भरी वस्तुएँ उपवर्ग हैं

यदि आपकी वस्तुओं को ORM का उपयोग करके जारी रखा जाता है, तो कई मामलों में आप डेटा स्टोर से बहुत जल्दी ऑब्जेक्ट लोड करने से बचने के लिए डायनेमिक प्रॉक्सी से निपटेंगे। ये परदे के पीछे आपकी ही कक्षा के उपवर्ग के रूप में लागू किए जाते हैं। इसका मतलब है कि this.getClass() == o.getClass()वापस आएगा false। उदाहरण के लिए:

Person saved = new Person("John Doe");
Long key = dao.save(saved);
dao.flush();
Person retrieved = dao.retrieve(key);
saved.getClass().equals(retrieved.getClass()); // Will return false if Person is loaded lazy

यदि आप एक ORM के साथ काम कर रहे हैं, तो प्रयोग o instanceof Personकेवल एक चीज है जो सही ढंग से व्यवहार करेगी।

आलसी भरी वस्तुओं में अशक्त क्षेत्र होते हैं

ORM आमतौर पर आलसी भरी वस्तुओं को लोड करने के लिए गेटर्स का उपयोग करते हैं। इसका मतलब है कि person.nameहो जाएगा nullअगर person, आलसी लोड है, भले ही person.getName()बलों लदान और रिटर्न "जॉन डो"। मेरे अनुभव में, यह फसल अक्सर hashCode()और अधिक होती है equals()

यदि आप एक ORM साथ हैं निपटने, हमेशा में ही टिककर खेल, और कभी क्षेत्र संदर्भ का उपयोग सुनिश्चित करें hashCode()और equals()

किसी वस्तु को सहेजने से उसकी स्थिति बदल जाएगी

लगातार ऑब्जेक्ट्स अक्सर ऑब्जेक्ट idकी कुंजी को रखने के लिए एक फ़ील्ड का उपयोग करते हैं । जब कोई ऑब्जेक्ट पहली बार सहेजा जाता है तो यह फ़ील्ड अपने आप अपडेट हो जाएगी। किसी आईडी फ़ील्ड का उपयोग न करें hashCode()। लेकिन आप इसमें इस्तेमाल कर सकते हैं equals()

एक पैटर्न जिसका मैं अक्सर उपयोग करता हूं

if (this.getId() == null) {
    return this == other;
}
else {
    return this.getId().equals(other.getId());
}

लेकिन: यदि आप शामिल नहीं कर सकते getId()में hashCode()। यदि आप करते हैं, जब कोई वस्तु बनी रहती है, तो उसके hashCodeपरिवर्तन। यदि ऑब्जेक्ट एक में है HashSet, तो आप इसे फिर कभी नहीं ढूंढेंगे।

मेरे Personउदाहरण में, मैं शायद के getName()लिए hashCodeऔर getId()प्लस getName()(सिर्फ व्यामोह के लिए) का उपयोग करूंगा equals()। यह ठीक है अगर इसके लिए "टकराव" के कुछ जोखिम हैं hashCode(), लेकिन इसके लिए कभी ठीक नहीं है equals()

hashCode() से गुणों के गैर-बदलते सबसेट का उपयोग करना चाहिए equals()


2
@ जोहान्स ब्रोडवॉल: मुझे समझ नहीं आया Saving an object will change it's state! hashCodeलौटना चाहिए int, तो आप कैसे उपयोग करेंगे getName()? आप अपने लिए एक उदाहरण दे सकते हैंhashCode
jimmybondy

@jimmybondy: getName एक स्ट्रिंग ऑब्जेक्ट लौटाएगा जिसमें एक हैशकोड भी है जिसका उपयोग किया जा सकता है
mateusz.fiolka

85

के बारे में एक स्पष्टीकरण obj.getClass() != getClass()

यह कथन equals()अमित्रत्व के उत्तराधिकार होने का परिणाम है । जेएलएस (जावा लैंग्वेज स्पेसिफिकेशन) निर्दिष्ट करता है कि यदि आवश्यक हो A.equals(B) == trueतो B.equals(A)वापस भी आना चाहिए true। यदि आप उस कथन को छोड़ देते हैं, जो उन वर्गों को विरासत में देता है जो equals()(और उसके व्यवहार को बदल देते हैं) इस विनिर्देश को तोड़ देंगे।

कथन के छोड़े जाने पर क्या होता है, इसके निम्नलिखित उदाहरण पर विचार करें:

    class A {
      int field1;

      A(int field1) {
        this.field1 = field1;
      }

      public boolean equals(Object other) {
        return (other != null && other instanceof A && ((A) other).field1 == field1);
      }
    }

    class B extends A {
        int field2;

        B(int field1, int field2) {
            super(field1);
            this.field2 = field2;
        }

        public boolean equals(Object other) {
            return (other != null && other instanceof B && ((B)other).field2 == field2 && super.equals(other));
        }
    }    

ऐसा करने से new A(1).equals(new A(1))इसके अलावा, new B(1,1).equals(new B(1,1))सच बाहर देते हैं, एकदम सही ढंग से उत्पन्न होती हैं।

यह सब बहुत अच्छा लग रहा है, लेकिन देखो कि क्या होता है अगर हम दोनों वर्गों का उपयोग करने की कोशिश करते हैं:

A a = new A(1);
B b = new B(1,1);
a.equals(b) == true;
b.equals(a) == false;

जाहिर है, यह गलत है।

यदि आप सममित स्थिति सुनिश्चित करना चाहते हैं। a = b यदि b = a और लिस्कोव प्रतिस्थापन सिद्धांत super.equals(other)न केवल Bउदाहरण के मामले में कहता है , बल्कि उदाहरण के लिए जाँच करें A:

if (other instanceof B )
   return (other != null && ((B)other).field2 == field2 && super.equals(other)); 
if (other instanceof A) return super.equals(other); 
   else return false;

जो आउटपुट देगा:

a.equals(b) == true;
b.equals(a) == true;

जहां, यदि aइसका संदर्भ नहीं है B, तो यह वर्ग का संदर्भ हो सकता है A(क्योंकि आप इसे बढ़ाते हैं), इस मामले में आप super.equals() भी कॉल करते हैं


2
आप इस तरह से सममित बना सकते हैं (यदि उपवर्ग ऑब्जेक्ट के साथ एक सुपरक्लास ऑब्जेक्ट की तुलना करें, तो हमेशा उपवर्ग के बराबर का उपयोग करें) यदि (obj.getClass ()! = This.getClass () और + obj.getClass ()) हैइन्स्टेंस (यह)। ) वापसी obj.equals (यह);
pihentagy

5
@pihentagy - तब मुझे स्टैकओवरफ़्लो मिलेगा जब कार्यान्वयन वर्ग समान पद्धति को ओवरराइड नहीं करता है। मज़ा नहीं।
रैन बीरन

2
आपको स्टैकओवरफ्लो नहीं मिलेगा। यदि समान पद्धति को ओवरराइड नहीं किया जाता है, तो आप फिर से उसी कोड को कॉल करेंगे, लेकिन पुनरावृत्ति के लिए शर्त हमेशा झूठी होगी!
जैकब रायहले

@ पिएजेंटैगी: यदि दो अलग-अलग व्युत्पन्न वर्ग हैं तो यह कैसे व्यवहार करता है? यदि कोई बशर्ते के ThingWithOptionSetAबराबर हो सकता है Thingकि सभी अतिरिक्त विकल्पों में डिफ़ॉल्ट मान हैं, और इसी तरह से ThingWithOptionSetB, तो यह संभव होना चाहिए ThingWithOptionSetAकि इसकी तुलना ThingWithOptionSetBकेवल एक ही के बराबर की जाए यदि दोनों वस्तुओं के सभी गैर-आधार गुण उनकी चूक से मेल खाते हों, लेकिन मैं नहीं देखता कि आप उसके लिए कैसे परीक्षण करते हैं।
सुपरकैट

7
इसके साथ समस्या यह है कि यह परिवर्तनशीलता को तोड़ती है। यदि आप जोड़ते हैं B b2 = new B(1,99), तो b.equals(a) == trueऔर a.equals(b2) == trueलेकिन b.equals(b2) == false
nickgrim

46

एक विरासत के अनुकूल कार्यान्वयन के लिए, ताल कोहेन के समाधान की जांच करें , मैं सही तरीके से बराबर () पद्धति को कैसे लागू करूं?

सारांश:

अपनी पुस्तक में प्रभावी जावा प्रोग्रामिंग लैंग्वेज गाइड (एडिसन-वेस्ले, 2001) में, जोशुआ बलोच का दावा है कि "एक तत्काल वर्ग का विस्तार करने और समान अनुबंध को संरक्षित करते हुए एक पहलू जोड़ने का कोई तरीका नहीं है।" ताल असहमत।

उसका समाधान एक और निरर्थक नेत्रहीन रूप से (दोनों) तरीके से कॉल करके समान () लागू करना है। आँख बंद करके () उपवर्गों द्वारा ओवरराइड किया जाता है, बराबर () विरासत में मिला है, और कभी भी ओवरराइड नहीं किया गया है।

उदाहरण:

class Point {
    private int x;
    private int y;
    protected boolean blindlyEquals(Object o) {
        if (!(o instanceof Point))
            return false;
        Point p = (Point)o;
        return (p.x == this.x && p.y == this.y);
    }
    public boolean equals(Object o) {
        return (this.blindlyEquals(o) && o.blindlyEquals(this));
    }
}

class ColorPoint extends Point {
    private Color c;
    protected boolean blindlyEquals(Object o) {
        if (!(o instanceof ColorPoint))
            return false;
        ColorPoint cp = (ColorPoint)o;
        return (super.blindlyEquals(cp) && 
        cp.color == this.color);
    }
}

ध्यान दें कि बराबर () को वंशानुगत पदानुक्रम में काम करना होगा यदि लिस्कोव प्रतिस्थापन सिद्धांत को संतुष्ट करना है।


10
यहां बताए गए कैनक्वल विधि पर एक नज़र डालें - एक ही सिद्धांत दोनों समाधानों को काम करता है, लेकिन कैनेक्वल के साथ आप एक ही फ़ील्ड की दो बार तुलना नहीं करते हैं (ऊपर, px == इस। दोनों दिशाओं में परीक्षण किया जाएगा): artima.com /lejava/articles/equality.html
Blaisorblade

2
किसी भी मामले में, मुझे नहीं लगता कि यह एक अच्छा विचार है। यह बराबरी के अनुबंध को अनावश्यक रूप से भ्रामक बनाता है - कोई व्यक्ति जो दो पॉइंट पैरामीटर, a और b लेता है, को इस संभावना के प्रति सचेत रहना होगा कि a.getX () == b.getX () और a.getY () == b.getY () सही हो सकता है, लेकिन a.equals (b) और b.equals (a) दोनों ही झूठे हो सकते हैं (यदि केवल एक ColorPoint है)।
केविन

मूल रूप से, यह ऐसा है if (this.getClass() != o.getClass()) return false, लेकिन इसमें लचीला है कि यह केवल तभी वापस आता है जब व्युत्पन्न वर्ग (तों) समान को संशोधित करने के लिए परेशान करता है। क्या वह सही है?
Aleksandr Dubinsky

31

अभी भी आश्चर्यचकित है कि इसके लिए अमरूद पुस्तकालय की सिफारिश किसी ने नहीं की।

 //Sample taken from a current working project of mine just to illustrate the idea

    @Override
    public int hashCode(){
        return Objects.hashCode(this.getDate(), this.datePattern);
    }

    @Override
    public boolean equals(Object obj){
        if ( ! obj instanceof DateAndPattern ) {
            return false;
        }
        return Objects.equal(((DateAndPattern)obj).getDate(), this.getDate())
                && Objects.equal(((DateAndPattern)obj).getDate(), this.getDatePattern());
    }

23
java.util.Objects.hash () और java.util.Objects.equals () जावा 7 (2011 में जारी) का हिस्सा हैं, इसलिए आपको इसके लिए अमरूद की आवश्यकता नहीं है।
हरमन

1
बेशक, लेकिन आपको इस बात से बचना चाहिए कि चूंकि Oracle जावा 6 के लिए अब सार्वजनिक अपडेट नहीं दे रहा है (फरवरी 2013 से यही स्थिति रही है)।
हरमन

6
आपका thisमें this.getDate()साधन कुछ भी नहीं (अव्यवस्था के अलावा अन्य)
स्टीव कू

1
आपके "नहीं उदाहरण" अभिव्यक्ति को एक अतिरिक्त ब्रैकेट की आवश्यकता है if (!(otherObject instanceof DateAndPattern)) {:। हेरन और स्टीव कू के साथ सहमत (हालांकि वह व्यक्तिगत पसंद की बात है), लेकिन फिर भी +1।
एमोस कारपेंटर

26

सुपर क्लास में java.lang.Object के रूप में दो तरीके हैं। हमें उन्हें कस्टम ऑब्जेक्ट पर ओवरराइड करने की आवश्यकता है।

public boolean equals(Object obj)
public int hashCode()

समान वस्तुओं को समान हैश कोड का उत्पादन करना चाहिए जब तक वे समान हैं, हालांकि असमान वस्तुओं को अलग-अलग हैश कोड का उत्पादन करने की आवश्यकता नहीं है।

public class Test
{
    private int num;
    private String data;
    public boolean equals(Object obj)
    {
        if(this == obj)
            return true;
        if((obj == null) || (obj.getClass() != this.getClass()))
            return false;
        // object must be Test at this point
        Test test = (Test)obj;
        return num == test.num &&
        (data == test.data || (data != null && data.equals(test.data)));
    }

    public int hashCode()
    {
        int hash = 7;
        hash = 31 * hash + num;
        hash = 31 * hash + (null == data ? 0 : data.hashCode());
        return hash;
    }

    // other methods
}

यदि आप अधिक प्राप्त करना चाहते हैं, तो कृपया इस लिंक को http://www.javaranch.com/journal/2002/10/equalhash.html देखें

यह एक और उदाहरण है, http://java67.blogspot.com/2013/04/example-of-overriding-equals-hashcode-compareTo-java-method.html

मज़े करो! @। @


क्षमा करें, लेकिन मैं इस कथन को हैशकोड विधि के बारे में नहीं समझता: यह कानूनी नहीं है यदि यह बराबरी की तुलना में अधिक चर का उपयोग करता है ()। लेकिन अगर मैं अधिक चर के साथ कोड करता हूं, तो मेरा कोड संकलित करता है। यह कानूनी क्यों नहीं है?
Adrr83

19

सदस्य समानता की जाँच करने से पहले वर्ग समानता के लिए अपनी जाँच करने के कुछ तरीके हैं, और मुझे लगता है कि दोनों सही परिस्थितियों में उपयोगी हैं।

  1. instanceofऑपरेटर का उपयोग करें ।
  2. का उपयोग करें this.getClass().equals(that.getClass())

मैं एक finalसमान कार्यान्वयन में # 1 का उपयोग करता हूं , या एक इंटरफ़ेस लागू करते समय जो समान के लिए एक एल्गोरिथ्म को निर्धारित करता है (जैसे java.utilसंग्रह इंटरफेस - के साथ जांच करने का सही तरीका(obj instanceof Set) आपके या जो भी इंटरफ़ेस आप लागू कर रहे हैं उसके )। यह आम तौर पर एक बुरा विकल्प होता है जब बराबरी पर रोक लगाई जा सकती है क्योंकि यह सममिति संपत्ति को तोड़ता है।

विकल्प # 2 वर्ग को समतुल्यता या ब्रेकिंग समरूपता के बिना सुरक्षित रूप से विस्तारित करने की अनुमति देता है।

यदि आपकी कक्षा भी है Comparable, equalsऔर compareToविधियाँ भी सुसंगत होनी चाहिए। यहां Comparableकक्षा में समान पद्धति के लिए एक टेम्पलेट दिया गया है :

final class MyClass implements Comparable<MyClass>
{

  

  @Override
  public boolean equals(Object obj)
  {
    /* If compareTo and equals aren't final, we should check with getClass instead. */
    if (!(obj instanceof MyClass)) 
      return false;
    return compareTo((MyClass) obj) == 0;
  }

}

1
इसके लिए +1। न तो getClass () और न ही उदाहरण के लिए एक रामबाण है, और यह दोनों कैसे दृष्टिकोण करने के लिए एक अच्छा विवरण है। ऐसा मत सोचो कि ऐसा करने के लिए कोई कारण नहीं है। बराबरी () का उपयोग करने के बजाय यह .getClass () == that.getClass ()।
पॉल कैंटरेल

इसके साथ एक समस्या है। बेनामी वर्ग जो किसी भी पहलू को नहीं जोड़ते हैं और न ही बराबर पद्धति को ओवरराइड करते हैं, भले ही वे समान होने के बावजूद गेटक्लास चेक को विफल कर देंगे।
बजे स्टीवनबोट

@ छोटे यह मेरे लिए स्पष्ट नहीं है कि विभिन्न प्रकार की वस्तुएं समान होनी चाहिए; मैं एक सामान्य अनाम वर्ग के रूप में एक इंटरफ़ेस के विभिन्न कार्यान्वयन के बारे में सोच रहा हूं। क्या आप अपने आधार का समर्थन करने के लिए एक उदाहरण दे सकते हैं?
इरिक्सन

MyClass a = नया MyClass (123); MyClass b = new MyClass (123) {// कुछ विधि को ओवरराइड करें}; //। a.equals (b) इस का उपयोग करते समय गलत है ।getClass ()। बराबर (that.getClass ())
steinybot

1
@ चमकदार अधिकार। जैसा कि ज्यादातर मामलों में होना चाहिए, खासकर अगर एक विधि जोड़े जाने के बजाय ओवरराइड होती है। ऊपर मेरे उदाहरण पर विचार करें। यदि यह नहीं थे final, और compareTo()विधि को क्रम क्रम को उलटने के लिए ओवरराइड किया गया था, तो उपवर्ग और सुपरक्लास के उदाहरणों को समान नहीं माना जाना चाहिए। जब इन वस्तुओं को एक पेड़ में एक साथ इस्तेमाल किया गया था, तो instanceofकार्यान्वयन के अनुसार "बराबर" होने वाली चाबियां खोजने योग्य नहीं हो सकती हैं।
एरिकसन

16

बराबरी के लिए, इस पर गौर बराबर का राज द्वारा एंजेलिका लैंगर । मुझे इससे बहुत प्यार है। वह जावा में जेनरिक के बारे में एक बहुत अच्छा प्रश्न है । यहां उसके अन्य लेख देखें (नीचे स्क्रॉल करें "कोर जावा"), जहां वह भाग -2 और "मिश्रित प्रकार की तुलना" भी करती है। उन्हें पढ़कर मजा आया!


11

बराबर () विधि का उपयोग दो वस्तुओं की समानता को निर्धारित करने के लिए किया जाता है।

10 के बराबर मान हमेशा 10 के बराबर होता है। लेकिन यह बराबरी () विधि दो वस्तुओं की समानता के बारे में है। जब हम वस्तु कहते हैं, तो उसके गुण होंगे। समानता के बारे में निर्णय लेने के लिए उन गुणों पर विचार किया जाता है। यह आवश्यक नहीं है कि समानता को निर्धारित करने के लिए सभी गुणों को ध्यान में रखा जाना चाहिए और वर्ग परिभाषा और संदर्भ के संबंध में यह तय किया जा सकता है। तब बराबरी () पद्धति को ओवरराइड किया जा सकता है।

जब भी हम समतुल्य () विधि को ओवरराइड करते हैं, तो हमें हमेशा हैशकोड () पद्धति को ओवरराइड करना चाहिए। यदि नहीं, तो क्या होगा? यदि हम अपने एप्लिकेशन में हैशटेबल्स का उपयोग करते हैं, तो यह अपेक्षा के अनुरूप व्यवहार नहीं करेगा। चूंकि हैशकोड का उपयोग संग्रहीत मूल्यों की समानता को निर्धारित करने में किया जाता है, यह एक कुंजी के लिए सही संगत मान नहीं लौटाएगा।

डिफ़ॉल्ट कार्यान्वयन दिया गया है हैशकोड () ऑब्जेक्ट क्लास में विधि ऑब्जेक्ट के आंतरिक पते का उपयोग करता है और इसे पूर्णांक में परिवर्तित करता है और इसे वापस करता है।

public class Tiger {
  private String color;
  private String stripePattern;
  private int height;

  @Override
  public boolean equals(Object object) {
    boolean result = false;
    if (object == null || object.getClass() != getClass()) {
      result = false;
    } else {
      Tiger tiger = (Tiger) object;
      if (this.color == tiger.getColor()
          && this.stripePattern == tiger.getStripePattern()) {
        result = true;
      }
    }
    return result;
  }

  // just omitted null checks
  @Override
  public int hashCode() {
    int hash = 3;
    hash = 7 * hash + this.color.hashCode();
    hash = 7 * hash + this.stripePattern.hashCode();
    return hash;
  }

  public static void main(String args[]) {
    Tiger bengalTiger1 = new Tiger("Yellow", "Dense", 3);
    Tiger bengalTiger2 = new Tiger("Yellow", "Dense", 2);
    Tiger siberianTiger = new Tiger("White", "Sparse", 4);
    System.out.println("bengalTiger1 and bengalTiger2: "
        + bengalTiger1.equals(bengalTiger2));
    System.out.println("bengalTiger1 and siberianTiger: "
        + bengalTiger1.equals(siberianTiger));

    System.out.println("bengalTiger1 hashCode: " + bengalTiger1.hashCode());
    System.out.println("bengalTiger2 hashCode: " + bengalTiger2.hashCode());
    System.out.println("siberianTiger hashCode: "
        + siberianTiger.hashCode());
  }

  public String getColor() {
    return color;
  }

  public String getStripePattern() {
    return stripePattern;
  }

  public Tiger(String color, String stripePattern, int height) {
    this.color = color;
    this.stripePattern = stripePattern;
    this.height = height;

  }
}

उदाहरण कोड आउटपुट:

bengalTiger1 and bengalTiger2: true 
bengalTiger1 and siberianTiger: false 
bengalTiger1 hashCode: 1398212510 
bengalTiger2 hashCode: 1398212510 
siberianTiger hashCode: 1227465966

7

तार्किक रूप से हमारे पास:

a.getClass().equals(b.getClass()) && a.equals(b)a.hashCode() == b.hashCode()

लेकिन नहीं उपाध्यक्ष प्रतिकूल!


6

एक गेचा मुझे मिला है, जहां दो वस्तुओं में एक-दूसरे के संदर्भ होते हैं (एक उदाहरण माता-पिता / बच्चे का रिश्ता है जो सभी बच्चों को पाने के लिए माता-पिता की सुविधा पद्धति के साथ है)।
उदाहरण के लिए हाइबरनेट मैपिंग करते समय इस तरह की चीजें काफी आम हैं।

यदि आप अपने हैशकोड या समतुल्य परीक्षणों के दोनों सिरों को शामिल करते हैं तो एक पुनरावर्ती लूप में आना संभव है जो एक StackOverflowException में समाप्त होता है।
सरलतम उपाय तरीकों में getChildren संग्रह को शामिल नहीं करना है।


5
मुझे लगता है कि यहां अंतर्निहित सिद्धांत किसी वस्तु के गुण , समुच्चय और सह - संबंध के बीच अंतर करना है। Asssociations में भाग नहीं लेना चाहिए equals()। अगर एक पागल वैज्ञानिक ने मुझे एक डुप्लिकेट बनाया तो हम समकक्ष होंगे। लेकिन हमारे पास एक ही पिता नहीं होगा।
राएडवल्ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.