2010-05-31 15 views
21

में मिलाकर मेरे पास हैशकोड() लागू एक वेक्टर क्लास है। यह मेरे द्वारा नहीं लिखा गया था, लेकिन 2 प्रमुख संख्याओं का उपयोग करता है जिसके द्वारा उन्हें XORing से पहले 2 वेक्टर घटकों को गुणा करना है। यहां यह है:जावा हैशकोड को "मास्टर" हैशकोड

/*class Vector2f*/ 
... 
    public int hashCode() 
    { 
     return 997 * ((int)x)^991 * ((int)y); //large primes! 
    } 

... चूंकि यह एक स्थापित जावा लाइब्रेरी से है, मुझे पता है कि यह ठीक काम करता है।

तब मेरे पास एक सीमा वर्ग है, जिसमें 2 वैक्टर, "प्रारंभ" और "अंत" (रेखा के अंत बिंदुओं का प्रतिनिधित्व) होता है। इन 2 वैक्टरों के मूल्य सीमा को दर्शाते हैं।

/*class Boundary*/ 
... 
    public int hashCode() 
    { 
     return 1013 * (start.hashCode())^1009 * (end.hashCode()); 
    } 

यहाँ मैं वैक्टर की अद्वितीय 2-टपल के लिए एक अच्छा hashCode() बनाने (& अंत शुरू) इस सीमा का गठन करने का प्रयास किया है। मेरा सवाल: क्या यह हैशकोड() कार्यान्वयन काम करने जा रहा है?

(ध्यान दें कि मैंने बाद वाले हैशकोड() कार्यान्वयन में 2 अलग-अलग प्राइम नंबरों का उपयोग किया है; मुझे नहीं पता कि यह आवश्यक है, लेकिन सामान्य कारकों से बचने की कोशिश करते समय खेद से सुरक्षित होना बेहतर है, मुझे लगता है - चूंकि मुझे लगता है कि यही कारण है कि हैशिंग फ़ंक्शन के लिए प्रिम्स लोकप्रिय हैं।)

उत्तर

16

यह सामान्य अभ्यास है। यह मेरे लिए बहुत उचित लग रहा है। यदि आप ग्रहण का उपयोग कर रहे हैं, तो आपको यह पता होना चाहिए कि यह आपके लिए equals और hashCode उत्पन्न कर सकता है-बस स्रोत मेनू देखें। यह वही काम करेगा-आपके फ़ील्ड का आकलन करें और equals विधि बनाएं जो उन सभी को जांचता है, फिर n प्राइम नंबर चुनें और hashCode विधि बनाने के लिए आपने जो किया है वह करें।

+0

धन्यवाद समीर, मुझे नहीं पता था कि ग्रहण में यह था। –

3

प्राइम संख्याओं का उपयोग करने का कारण (वे जरूरी नहीं कि "बड़े" प्रमुख संख्याएं हों) वास्तव में आम कारकों से बचें।

हैश कोड का उपयोग हैश-आधारित संग्रह वर्गों जैसे HashSet और HashMap द्वारा किया जाता है। यदि नक्शे में ऑब्जेक्ट्स के हैश कोड संभवतः भिन्न होते हैं तो वे सबसे अच्छे काम करते हैं (यदि ऑब्जेक्ट्स के हैंश कोड समान हैं तो उन्हें ऑब्जेक्ट्स को अलग करने के लिए और अधिक काम करना होगा)।

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

+0

बस मुझे यह अधिकार मिलता है, क्या यह अनुशंसा की जाती है कि मैं अंतर्निहित वेक्टर 2f.hashCode() कार्यान्वयन में उपयोग की जाने वाली जोड़ी के मुकाबले बाउंडरी.hashCode() में प्राइम्स की * अलग जोड़ी * का उपयोग करता हूं? या अगर मैं 997 और 991 दोनों में इस्तेमाल करता तो यह वही होगा? AFAIK, चूंकि एक्सओआर बिट्सिंग बिट्स है, इसलिए एक्सओआर के परिणामस्वरूप पूर्णांक एक प्राइम (या गैर-प्राइम) होने के लिए जरूरी नहीं है, जिसका अर्थ यह है कि इससे कोई फर्क नहीं पड़ता कि मैं प्राइम्स की एक ही जोड़ी का उपयोग करता हूं? –

+0

मुझे पूरी तरह से यकीन नहीं है; यदि एक्सओआर के बजाय + का उपयोग किया गया था, तो यह स्पष्ट होगा - आपको विभिन्न प्राइम का उपयोग करना चाहिए। तो मैं बस सुरक्षित होने के लिए ऐसा करूंगा। ध्यान दें कि एक्सओआर लगभग संख्या जोड़ने की तरह है, लेकिन बिट्स ले जाने के बिना (यानी '1^1 = 0' और' 10' नहीं, थोड़ा आगे ले जाना)। मैंने सोचा नहीं है कि यह वास्तव में परिणाम को कैसे प्रभावित करेगा। – Jesper

+0

@ निक विगिल मुझे विश्वास है कि महत्वपूर्ण बात यह है कि प्राइम को हैशटेबल के अंतर्निहित सरणी के आकार का कारक नहीं मिला है। यदि आप 17 से गुणा करते हैं, और सरणी का आकार 34 है, तो सभी ऑब्जेक्ट्स 0 या 17 स्थिति (अंत में टकराव के कारण) पर समाप्त हो जाएंगे। – ILMTitan

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