2011-03-31 11 views
6

शामिल मेरी कोड है:HashSet यहां विधि, अजीब व्यवहार

public class testGui { 



    public static void main(String[] arg){ 
     class TESTS{ 
      String t; 

      public TESTS(String t){ 
       this.t = t; 
      } 

      @Override 
      public boolean equals(Object x){ 
       System.out.println("My method is called..."); 
       if(x instanceof TESTS){ 
        TESTS zzz = (TESTS) x; 
        return zzz.t.compareTo(t)==0; 
       } 
       else return false; 
      } 
     } 
     HashSet<TESTS> allItems = new HashSet<TESTS>(); 
     allItems.add(new TESTS("a")); 
     allItems.add(new TESTS("a")); 
     System.out.println(allItems.contains(new TESTS("a"))); 
    } 

} 

मैं नहीं मिलता है क्यों HashSet शामिल विधि बुला नहीं है मेरी बराबरी पद्धति के रूप में अपने विनिर्देशों में mentionned:

अधिक औपचारिक रूप से , अगर यह सेट कोई तत्व ई तरह के होते हैं इस सेट करने के लिए, निर्दिष्ट तत्व को जोड़ता है ओ, कि (ओ == बातिल ई == बातिल: o.equals (ई))

मेरा कोड गलत लौट रहा है और मेरे बराबर विधि में नहीं जा रहा है।

उत्तर देने के लिए बहुत बहुत धन्यवाद!

उत्तर

13

जब आप equals ओवरराइड करते हैं, तो आपको hashCode ओवरराइड करना होगा। अन्यथा, समान वस्तुओं में अलग हैश कोड होंगे और असमान माना जाएगा।

यह भी दृढ़ता से अनुशंसा की जाती है कि केवलhashCode ओवरराइड न करें। लेकिन यह आवश्यक नहीं है, क्योंकि असमान वस्तुओं में एक ही हैश कोड हो सकता है।

+2

उन्हें असमान नहीं माना जाएगा। यह सिर्फ इतना है कि हैशसेट भी बराबर विधि का आह्वान नहीं करेगा क्योंकि यह केवल हैशकोड के लिए एक ही बाल्टी की ओर जाता है। और केवल हैशकोड को ओवरराइड करने का कोई अर्थ नहीं है, क्योंकि हैशसेट हमेशा उसी हैशकोड वाले ऑब्जेक्ट्स के बराबर कॉल करेगा। –

+0

@ जेबी, हां, तथ्य यह है कि वे अलग-अलग बाल्टी का नेतृत्व करते हैं, इसका मतलब है कि उन्हें 'असमान' माना जाता है (विभिन्न वस्तुओं के रूप में माना जाता है)। जब मैं उस शब्द का उपयोग करता हूं तो मैं 'बराबर' विधि का जिक्र नहीं कर रहा हूं। मैं केवल 'हैशकोड' को ओवरराइड करने पर भी सहमत हूं, इसलिए मैं इसके खिलाफ दृढ़ता से अनुशंसा करता हूं। हालांकि, यह अनुबंध तोड़ नहीं है। –

+1

यह अच्छा होगा अगर जावा दस्तावेज का उल्लेख है कि हैशकोड को पहले कहा जाता है। मैं जावा 5 में इस मुद्दे से जला दिया गया। – Aaron

3

आपको hashCode भी लागू करना चाहिए, ताकि यह equals के साथ संगत हो। HashSethashCode विधि का उपयोग यह तय करने के लिए करता है कि कौन सा बाल्टी किसी आइटम को डालने के लिए है, और केवल equals पर कॉल करता है जब दो आइटम का हैश कोड समान होता है।

प्रभावी जावा, 2 संस्करण चर्चा इस नियम (और यह तोड़ने के परिणामों) आइटम 9 में: हमेशा hashCode ओवरराइड जब आप equals ओवरराइड।

+0

बहुत बहुत धन्यवाद, यह वास्तव में सहायक था, मैंने जवाब देने से पहले जवाब प्राप्त किया (पता नहीं था कि सवाल कैसे रद्द किया जाए), लेकिन आपने जो लिखा है वह मैंने किया है और यह मेरी समस्या हल हो गया;)। – Abbadon

7

हैशसेट प्रत्येक ऑब्जेक्ट के हैशकोड पर निर्भर करता है। बराबर विधि कहा जाता है, हैशकोड विधि कहा जाएगा। यदि हैशकोड बराबर हैं, तो हैशसेट मानता है कि यह बराबर विधि का मूल्यांकन करने योग्य है।

एक hashCode विधि लागू ऐसी है कि अगर a.equals (ख) == सच है, तो a.hashCode() == b.hashCode()

और यह काम कर रहा जैसा कि आप उम्मीद करेंगे शुरू कर देना चाहिए।

0

जैसा कि अधिकांश टिप्पणियां हुई हैं ... हैशकोड विधि (नीचे नमूना) को ओवरराइड करें और आपको अच्छा होना चाहिए।

@Override 
     public int hashCode() { 
      return t.hashCode()*31; 
     } 
+0

31 से गुणा करके आपको क्या लाभ होता है? –

+0

यह थ्रेड मदद करेगा http://stackoverflow.com/questions/299304/why-does-javas-hashcode-in-string-use-31-as-a-multiplier – Prasanna

संबंधित मुद्दे