2010-10-06 8 views
8

कभी-कभी मुझे अपने कई इंस्टेंस सदस्यों के हैशकोड को जोड़कर ओबीजे की हैशकोड() विधि को कार्यान्वित करने की आवश्यकता होती है। उदाहरण के लिए, यदि संयोजन obj के सदस्यों को एक, b, और c है, मैं अक्सर ppl यह रूप मेंहैशकोड() को लागू करने का पसंदीदा तरीका क्या है?


int hashCode(){ 
    return 31 * 31 * a.hashCode() + 31 * b.hashCode() + c.hashCode(); 
} 

जहां इस जादुई संख्या 31 से आता है लागू करते हुए देखना? क्या यह 4-बाइट्स या सिर्फ एक प्रमुख संख्या की लंबाई है?

हैशकोड() को लागू करने का कोई अन्य पसंदीदा/मानक तरीका है?

+0

इसी तरह (लेकिन आवश्यक रूप से डुप्लिकेट नहीं): http://stackoverflow.com/questions/3613102/why-use-a-prime-number-in-hashcode –

+0

प्राइम 31 का उपयोग स्ट्रिंग.hashCode() में किया जाता है एक अच्छा प्रधान है क्योंकि कई अलग-अलग संभावित पात्र नहीं हैं, हालांकि मैं बड़े प्राइम का उपयोग करता हूं। "रोचक" प्राइम्स के लिए एक अच्छी साइट http://primes.utm.edu/curios/ –

उत्तर

8

Effective Java's recipe देखें। यह सिर्फ सबसे अच्छा स्रोत है, हाथ नीचे।

एक प्रमुख संख्या का उपयोग डोमेन को जानने के बिना उचित रूप से अच्छा वितरण प्राप्त करने का प्रयास करना है। एक ही मूल्य में अतिप्रवाह होने में कुछ समय लगेगा। अगर मैं सही ढंग से याद करता हूं तो मूल्य 31 बहुत मनमाना है।

बलोच के अनुसार (वह एक प्रारंभिक मूल्य और निरंतर गुणक के रूप में 37 के रूप में 17 का उपयोग करता है):

एक अशून्य प्रारंभिक मूल्य प्रयोग किया जाता है (...) तो हैश मान प्रारंभिक से प्रभावित होगा फ़ील्ड जिनके हैश मान (...) शून्य है। यदि शून्य का उपयोग के रूप में किया गया था प्रारंभिक मान (...) समग्र हैश मान किसी ऐसे प्रारंभिक फ़ील्ड से अप्रभावित होगा, जो टकराव को बढ़ा सकता है। मान 17 मनमाने ढंग से है।
...
गुणक 37 चुना गया था क्योंकि यह एक विषम प्रधान है। यदि यह भी था और गुणा बहती है, तो जानकारी खो जाएगी क्योंकि गुणा दो से स्थानांतरित करने के बराबर है। प्राइम नंबर का उपयोग करने के फायदे कम स्पष्ट हैं, लेकिन इस उद्देश्य के लिए प्राइम का उपयोग करना पारंपरिक है।

+0

सीडब्लू है क्योंकि मैं सिर्फ ब्लैक को लापरवाही से उद्धृत कर रहा हूं। –

+4

प्रभावी जावा के दूसरे संस्करण में, जोश ब्लोच 37 के बजाय 31 का उपयोग करता है। वह उस विकल्प को समझाता है: "31 की एक अच्छी संपत्ति यह है कि गुणा को एक शिफ्ट द्वारा प्रतिस्थापित किया जा सकता है और बेहतर प्रदर्शन के लिए घटाव: 31 * i = = (i << 5) - i'। आधुनिक वीएम स्वचालित रूप से इस तरह के अनुकूलन करते हैं। " – ColinD

2

उपयोग HashCodeBuilder कॉमन्स लैंग से:

public int hashCode() { 
    return HashCodeBuilder.reflectionHashCode(this); 
} 

तरीके प्रतिबिंब का उपयोग किए बिना यह करने के लिए API देखें। आप इसे बता सकते हैं कि कौन से फ़ील्ड शामिल हैं, या किस पर अनदेखा करना है।

बराबर विधि को ओवरराइड करने के लिए इक्वाल्सबिल्डर भी देखें।

6

एक अच्छा विकल्प Guava की Objects.hashCode विधि है। यह तर्क के किसी भी संख्या लेता है और एक hashCode उन पर आधारित बनाता है:

@Override public int hashCode() { 
    return Objects.hashCode(a, b, c); 
} 
0

मूल रूप से, अपने हैश कोड अपने POJO की प्रमुख पैमाना होनी चाहिए। एक उदाहरण नीचे है।

public int hashCode() { 
    int hash = 0; 
    if (getRollId() != null) { 
     hash += getRollId().hashCode(); 
    } 
    if (getName() != null) { 
     hash += getName().hashCode(); 
    } 
    return hash == 0 ? System.identityHashCode(this) : hash; 
} 

उपरोक्त उदाहरण में, रोल आईडी और नाम उस POJO का मुख्य पैरामीटर है।

यह एक अच्छा अभ्यास है यदि आप केवल उसी पैरामीटर को हैशकोड विधि में जोड़ते हैं जिसे आप उसी POJO की Eqauls विधि में जोड़ते हैं।

1

इसे अपने आईडीई का उपयोग करके उत्पन्न करें।

0

मेरा मानना ​​है कि निम्नलिखित सरल परिदृश्यों के लिए एक अच्छा अभ्यास है: यदि आपकी कक्षा में कोई भी पाठक सदस्य हैं, तो वे ऑब्जेक्ट के हैशकोड उत्पन्न करने के लिए अच्छे उम्मीदवार होंगे। यदि आपकी कक्षा में, केवल उत्परिवर्तनीय सदस्य हैं, तो आप एक पाठक int फ़ील्ड बना सकते हैं जो कि कन्स्ट्रक्टर को पास किए गए गैर-शून्य मानों के आधार पर मान प्राप्त करता है।