2013-07-29 7 views
9

तो मैं hashCode() और बराबरी() विधि पर एक सवाल हैhashCode() और बराबरी() विधि

चलो कहते हैं कि मैं सिर्फ overridng एक बहुत ही बुनियादी प्रोग्राम लिखने दोनों ही methodes

import java.util.*; 

class Employee 
{ 
    private String name; 
    private int empid; 


    public Employee(String name,int empid) 
    { 
     this.name=name; 
     this.empid=empid; 
    } 


    public int getEmpid() 
    { 
     return empid; 
    } 


    public String getName() 
    { 
     return name; 
    } 


    public boolean equals(Object obj) 
    { 
     System.out.println("equals has just been called..."); 
     Employee e1=(Employee)obj; 
     return ((name.equals(e1.name)) && (empid==e1.empid)); 
    } 


    public int hashCode() 
    { 
     System.out.println("hashcode called..."); 
     return empid; 
    } 

} 

फिर , मान लीजिए कि मैं HashSet

class Five 
{ 
    public static void main(String args[]) 
    { 
     HashSet hs1=new HashSet(); 
     hs1.add(new Employee("Alex",25)); 
     hs1.add(new Employee("Peter",25)); 
     hs1.add(new Employee("Martin",25)); 
     hs1.add(new Employee("Alex",25)); 


     Iterator itr=hs1.iterator(); 

     while(itr.hasNext()) 
     { 
      Employee e=(Employee)itr.next(); 
      System.out.println(e.getEmpid()+"\t"+e.getName()); 
     } 


    } 

} 

में जोड़ सकते हैं और तत्वों पुनरावृत्ति करने के लिए एक और वर्ग बारे में अब सवाल है जब मैं एलेक्स फिर से जोड़ने के लिए के साथ एक ही बराबर empid (कोशिश) कैलोरी जाने हमेशा तुमको बार

नेतृत्व के रूप में वहाँ कोई सूचकांक n hashmap मामले में अगर यह पहले जाँच की जानी तो साथ पहले से यह सच वापस आ जाएगी और अन्य दो तत्वों (पीटर और मार्टिन) का आह्वान नहीं किया जाना चाहिए, लेकिन हमेशा कहा जाता बराबर एलेक्स जोड़ा है 3 बार

क्यों .. ??

एक ही बाल्टी के भीतर वस्तुओं को इंडेक्स भी है .. ??

+0

मैं हैशसेट स्रोत कोड पर एक नज़र डालेगा। स्मृति से यह वास्तव में एक नक्शा में शामिल करता है तो मैं indexOf संदेह है और बराबरी कि – RNJ

+0

अंकुर Lathi- nopss मेरी कुए में कई बार उपयोग किया जाता है अलग है – sandiee

उत्तर

12

Equals हमेशा जावा जोड़ने के संग्रह में hashCode विधि के बाद तत्वों को जोड़ने और हटाने के दौरान कहा जाता है। कारण यह है कि यदि निर्दिष्ट बाल्टी पर पहले से कोई तत्व है, तो JVM जांचता है कि यह वही तत्व है जिसे वह डालने का प्रयास कर रहा है। यदि बराबर बराबर लौटाता है तो तत्व को एक ही बाल्टी में जोड़ा जाता है लेकिन बाल्टी पर सूची के अंत में। तो अब आपके पास एक ही बाल्टी पर तत्वों की एक सूची नहीं है।

अब तत्व को पुनर्प्राप्त करते समय, पहले हैशकोड को वांछित बाल्टी तक पहुंचने के लिए बुलाया जाएगा और फिर सूची वांछित तत्व लाने के लिए बराबर का उपयोग करके स्कैन की जाएगी।

hashCode का आदर्श कार्यान्वयन सुनिश्चित करेगा कि प्रत्येक बाल्टी में सूची का आकार 1 है। और इसलिए तत्वों की पुनर्प्राप्ति ओ (1) जटिलता का उपयोग करके की जाती है। लेकिन यदि एक बाल्टी में सूची में संग्रहीत मल्टीप्ल तत्व हैं, तो तत्व का पुनरुत्थान ओ (एन) कॉम्प्लेक्स द्वारा किया जाएगा, जहां एन सूची का आकार है।

हैशसेट के मामले में बीटीडब्ल्यू बाल्टी पर कोई सूची नहीं बनाई गई है, बल्कि ऑब्जेक्ट को बस बदल दिया गया है यदि हैशकोड और बराबर समान हैं। आईएसटी निर्माण व्यवहार हैशप में है।

+2

मुझे लगता है कि hashCode-विधि कॉल बराबर-विधि कॉल बाद आता है ... – Puce

+1

@ पिस नंबर, हैशकोड को हमेशा बाल्टी प्राप्त करने के लिए पहले कहा जाता है, और तब बराबर को उस बाल्टी पर चीजों की जांच करने के लिए बुलाया जाता है। –

+0

Juned ahsan- thnx सर .. यह कुछ समय ले लिया, लेकिन अब यह मिला और जटिलता के स्पष्टीकरण बिंदु मैं चाहता हूँ – sandiee

0

एक ही हैश वाले एकाधिक ऑब्जेक्ट्स LinkedList के रूप में संग्रहीत हैं और नए तत्व HEAD पर जोड़े गए हैं। तो आपके मामले में सभी के पास एक ही हैश है, लिंक्डलिस्ट निम्नलिखित क्रम में है:

मार्टिन-> पीटर-> एलेक्स।

जब आप एक और "एलेक्स" जोड़ते हैं तो सूची हेड से निकलती है।

परीक्षण करने के लिए:

public boolean equals(Object obj) 
    { 
     Employee e1=(Employee)obj; 
     System.out.println(this.name + "'s equals has just been called against " + e1.name); 
     return ((name.equals(e1.name)) && (empid==e1.empid)); 
    } 
3

डालने के दौरान HashSet पहले कॉल hashCode और लग रहा है जो बाल्टी में नया मान के अंतर्गत आता है। यह देखता है कि पहले से ही तीन प्रविष्टियां हैं (सभी hashCode()25 के साथ)।

तो यह equals() का उपयोग करके तुलना करता है।और क्योंकि 3 प्रविष्टियां हैं, उन्हें equals() 3 बार कॉल करने के कारण सभी प्रविष्टियों की जांच करनी है।

+1

मैंने मूल रूप से सोचा कि उसने 'बराबर()' और 'हैशकोड()' अनुबंध का भी उल्लंघन किया है, लेकिन यह वास्तव में कुछ भी कैसे प्रभावित कर सकता है? यदि उनके पास एक ही 'empid' है, तो वे एक ही सरणी स्लॉट पर मैप करते हैं, और फिर' समान 'का उपयोग यह देखने के लिए किया जाता है कि' नाम 'मिलान हो या नहीं। मुझे कोई समस्या नहीं दिखाई दे रही है ... –

+3

'बराबर' और 'हैशकोड' विधियां मेरे लिए ठीक लगती हैं - 'बराबर' 'नाम' और 'empid' फ़ील्ड दोनों का उपयोग करती है, जबकि' हैशकोड 'केवल' empid' का उपयोग करता है। यह अनुबंध को मान्य नहीं करता है जो कहता है कि 'समान वस्तुओं में एक ही हैश कोड होना चाहिए, लेकिन उसी हैश कोड का मतलब यह नहीं है कि ऑब्जेक्ट बराबर हैं'। –

+0

असल में, मुझे लगता है कि जब तक बराबर रिटर्न बराबर होता है तब तक केवल प्रविष्टियों की तुलना करना पड़ता है, लेकिन एक बार बराबर बराबर रिटर्न रोक सकता है। तो इसका शायद मतलब है कि पहली प्रविष्टि ("एलेक्स", 25) कुछ कारणों से सूची के अंत में है? – Puce

3

एक java.util.HashSet एक java.util.HashMap इसके भंडारण के रूप में उपयोग करता है। मानचित्र में बाल्टी का प्रतिनिधित्व करने के लिए java.util.HashMap एक लिंक किए गए Entry ऑब्जेक्ट का उपयोग करता है।

Entry(int h, K k, V v, Entry<K,V> n) 
{ 
    value = v; 
    next = n; 
    key = k; 
    hash = h; 
} 
इस से

आप देख सकते हैं कि नए आइटम बाल्टी की शुरुआत (Entry n बाल्टी के पहले Entry पेश करता है) से जुड़ जाते हैं: यदि आप स्रोत कोड के माध्यम से पालन करें, तो आप java.util.HashMap.Entry की contructor को मिलेगा इसलिए जब एलेक्स दूसरी बार जोड़ने प्रत्येक मान

Martin -> Peter -> Alex 

,:, बकेट में आइटम (वहाँ केवल एक ही बाल्टी क्योंकि प्रत्येक Employee के लिए हैश कोड एक ही है) के क्रम में हो जाएगा तो अपने मामले में एलेक्स पहुंचने से पहले समानता के लिए जाँच की जाती है।

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