2012-01-31 13 views
5
में एक समानता विधि लिखें

सरल अंक के निम्न वर्ग के लिए एक समानता विधि जोड़ने पर विचार करें:कैसे जावा

public class Point { 

    private final int x; 
    private final int y; 

    public Point(int x, int y) { 
     this.x = x; 
     this.y = y; 
    } 

    public int getX() { 
     return x; 
    } 

    public int getY() { 
     return y; 
    } 

    // ... 
} 

// मेरी बराबरी की परिभाषा

public boolean equals(Point other) { 
    return (this.getX() == other.getX() && this.getY() == other.getY()); 
} 

क्या इस विधि के साथ गलत क्या है? ,

import java.util.HashSet; 

HashSet<Point> coll = new HashSet<Point>(); 
coll.add(p1); 

System.out.println(coll.contains(p2)); // prints false 

कैसे यह है कि coll p2 शामिल नहीं है हो सकता है, भले ही:

Point p1 = new Point(1, 2); 
Point p2 = new Point(1, 2); 

Point q = new Point(2, 3); 

System.out.println(p1.equals(p2)); // prints true 

System.out.println(p1.equals(q)); // prints false 

हालांकि, मुसीबत एक बार आप एक संग्रह में अंक डालना आरंभ शुरू होता है: पहली नज़र में, यह ठीक से काम करने लगता है पी 1 इसमें जोड़ा गया था, और पी 1 और पी 2 बराबर वस्तुएं हैं?

+0

अच्छी व्याख्या यहां: http://bytes.com/topic/java/insights/723476-overriding-equals-hashcode-methods इसे आंतरिक करें - यह जावा में सबसे मौलिक नियमों में से एक है और अक्सर साक्षात्कार प्रश्न है। –

उत्तर

8

हालांकि यह सच है कि आप hashCode() को लागू करना चाहिए जब आप equals() लागू, कि आपकी समस्या का कारण नहीं है।

यह equals() विधि नहीं है जिसे आप ढूंढ रहे हैं। बराबर विधि में हमेशा निम्नलिखित हस्ताक्षर होना चाहिए: "सार्वजनिक बूलियन बराबर (ऑब्जेक्ट ऑब्जेक्ट)"। यहां कुछ कोड है।

public boolean equals(Object object) 
{ 
    if (object == null) 
    { 
    return false; 
    } 

    if (this == object) 
    { 
    return true; 
    } 

    if (object instanceof Point) 
    { 
    Point point = (Point)object; 
    ... now do the comparison. 
    } 
    else 
    { 
    return false; 
    } 
} 

Apache EqualsBuilder class कार्यान्वयन के बराबर उपयोगी है।लिंक एक पुराना संस्करण है, लेकिन अभी भी लागू है।

यदि आपको अपाचे इक्वाल्सबिल्डर पसंद आया, तो आपको शायद Apache HashCodeBuilder class पसंद आएगा।

संपादित करें: मानक शॉर्टकट के लिए समान विधि उदाहरण अद्यतन किया गया है।

+1

इसे इंगित करने के लिए एकमात्र पोस्ट के लिए उपरोक्त। –

+0

@ लुइस: लगभग एकमात्र ... :-) – Dirk

+0

ठीक है। मैंने देखा कि मेरी टिप्पणी के रूप में केवल एक ही। –

4

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

यह अधिक विस्तार से समझाया गया है उदा। Effective Java 2nd Edition में, आइटम 9: जब आप के बराबर ओवरराइड करते हैं तो हमेशा हैशकोड ओवरराइड करें।

0

जब equals अधिभावी, आप भी hashCode ओवरराइड करने के लिए (विशेष रूप से, आप HashSet या HashMap उपयोग करने के लिए जा रहे हैं ...) है। एक उपयुक्त (हालांकि नहीं चतुर करने के लिए) कार्यान्वयन होगा:

int hashCode() { 
    return x * 31 + y; 
} 

एक और मुद्दा (कोई यमक इरादा): आप वास्तव में equals(Object) विधि वर्ग Object में परिभाषित अधिभावी नहीं कर रहे हैं, लेकिन इसके बजाय एक नया एक परिभाषित कर रहे हैं। सही तरीका होगा:

boolean equals(Object other) { 
    if (other == this) return true; 
    else if (!(other instanceof Point)) return false; 
    else { 
     Point p = (Point)other; 
     return x == p.getX() && y == p.getY(); 
    } 
} 

ध्यान दें, equals विधि एक pretty strong contract इसके साथ जुड़े हैं, जो आप को पूरा करने के है।

1

equals() पर अनुबंध के अनुसार आपको hashCode() को भी लागू करने की आवश्यकता है।

ध्यान दें कि यह, hashCode विधि जब भी इस विधि ओवरराइड की गई है ओवरराइड करने के लिए इतनी के रूप में hashCode विधि के लिए सामान्य अनुबंध है, जो कि बराबर वस्तुओं में कहा गया है बनाए रखने के लिए आम तौर पर आवश्यक है:

से JavaDoc equals() पर

बराबर हैश कोड होना चाहिए।

1

अन्य उत्तर के अलावा:

आप आईडीई के रूप में ग्रहण का उपयोग कर रहे हैं, तो आप बस "स्रोत" का उपयोग कर सकते -> "उत्पन्न hashCode() और बराबरी() एक बुनियादी कार्यान्वयन पाने के लिए के साथ करते हैं। ।! कि तुम क्या कभी आप चाहते

2

hashCode अधिभावी द्वारा अच्छी तरह से काम करता है

हमेशा

याद रखें:। ओवरराइड hashCode जब आप बराबरी ओवरराइड

@Override public int hashCode() { 
     return (41 * (41 + getX()) + getY()); 
    } 

यह हैशकोड का मेरा कार्यान्वयन है।

+0

यह एक अद्वितीय हैश उत्पन्न नहीं करता है ... 2 सरल उदाहरण 'x = 1',' y = 0', 'हैश = 1722' या' x = 0', 'y = 41', 'हैश = 1722' – Basic