2009-11-06 13 views
5

हमें बताया गया है कि हमें अपनी कक्षाओं के लिए हैशकोड() को लागू करना चाहिए, लेकिन मेरे जैसे अधिकांश लोगों को यह नहीं पता कि यह कैसे करना है या अगर हमें "गलत" मिलता है तो क्या होता है। उदाहरण के लिए मुझे पेड़ (Finding the most frequent subtrees in a collection of (parse) trees) में इंडेक्सिंग नोड्स के लिए हैश फ़ंक्शन की आवश्यकता है। इस मामले में मुझे क्रमशः बाल नोड्स के आधार पर हैशकोड उत्पन्न करने की आवश्यकता है, उदा।औसत प्रोग्रामर के लिए "अच्छा पर्याप्त" हैश फ़ंक्शन है?

hashCode = function(child1.hashCode, child2.hashCode, ...) 

hashCodes उत्तरों की एक recent discussion में तार के लिए एक हैश और भी bitshifting (एक लंबे प्रधानमंत्री और 31 के आधार पर) शामिल थे। स्ट्रिंग हैश है:

// adapted from String.hashCode() 
public static long hash(String string) { 
    long h = 1125899906842597L; // prime 
    int len = string.length(); 

    for (int i = 0; i < len; i++) { 
    h = 31*h + string.charAt(i); 
    } 
    return h; 
} 

मुझे सुरक्षा में रूचि नहीं है और टकराव नहीं है। क्या आदेशित वस्तुओं के हैशकोड के संयोजन के लिए एक "सार्वभौमिक कार्य" है जो नुकसान से अधिक अच्छा होगा (और इसे बिल्कुल कॉल करने से ज्यादा अच्छा नहीं)?

क्या ऐसी साइट भी है जहां हम आम मामलों को देख सकते हैं? तार, सूचियां, आदि)

मैंने एक भाषा निर्दिष्ट नहीं की क्योंकि मुझे उम्मीद थी कि सार्वभौमिक दृष्टिकोण थे। लेकिन अगर यह गंभीरता से भाषा-विशिष्ट है तो कृपया भाषा को इंगित करें और यह सार्वभौमिक क्यों नहीं है।

अद्यतन आईडीई के हैशकोड जनरेटर का उपयोग करने के लिए दो सुझाव हैं। यह एक उत्कृष्ट डिफ़ॉल्ट लगता है; यहाँ Netbeans है:

public int hashCode() { 
    int hash = 5; 
// objects 
    hash = 97 * hash + (this.rootElement != null ? this.rootElement.hashCode() : 0); 
    hash = 97 * hash + (this.tableElement != null ? this.tableElement.hashCode() : 0); 
// a string 
    hash = 97 * hash + (this.tag != null ? this.tag.hashCode() : 0); 
    return hash; 
} 

उत्तर

4

जोशुआ ब्लोच के Effective Java में एक उत्कृष्ट हैशकोड() है। नमूना अध्याय 3, "सभी ऑब्जेक्ट्स के लिए सामान्य तरीके" नि: शुल्क था (ठीक है, इसके लिए सूर्य की पुरानी साइट पर एक पृष्ठ था जब यह वापस किया जाता था। यदि आप खोज करते हैं तो आपको अभी भी उस अध्याय का पीडीएफ संस्करण मिल रहा है कहीं)।

आप अपाचे कॉमन्स लैंग में HashCodeBuilder के स्रोत को भी देख सकते हैं, लेकिन इसे उद्धृत किए बिना कक्षा के लिए कॉपी न करें। वास्तव में इस बारे में जानने के लिए समय बिताया गया है - यह आपको एक बेहतर व्यक्ति बना देगा।

+0

यह वही दिखता है जो मैं चाहता था। कॉमन्स से उद्धरण के लिए: "यह वर्ग किसी भी वर्ग के लिए एक अच्छी हैशकोड विधि बनाने के लिए सक्षम बनाता है। यह जोशुआ ब्लोच द्वारा प्रभावशाली जावा पुस्तक में निर्धारित नियमों का पालन करता है। एक अच्छी हैशकोड विधि लिखना वास्तव में काफी मुश्किल है। इस वर्ग का लक्ष्य है प्रक्रिया को सरल बनाएं। " मुझे संदेह है कि यह मुझे एक बेहतर व्यक्ति बना देगा (हालांकि मुझे लेखकों के नैतिक अधिकारों की परवाह है) लेकिन मुझे उम्मीद है कि यह मुझे एक बेहतर प्रोग्रामर बना देगा ... –

+0

ब्लोच के दृष्टिकोण के बाद से स्वीकार किया गया है जो मैं ढूंढ रहा था –

+0

दुर्भाग्य से वे लिंक अब मर चुके हैं। :( – Skrylar

1

आप Windows का उपयोग कर रहे हैं, तो आप HashData() उपयोग कर सकते हैं।

+0

ठीक है, तो यह जावा है, इसलिए कभी भी ध्यान न दें। –

+0

इसका उपयोग सी # कक्षा में कैसे किया जाएगा? –

+0

मुझे सी # के बारे में जानकर खुशी हुई - मैंने विशेष रूप से जावा निर्दिष्ट नहीं किया और मुझे लगता है कि भाषा स्वतंत्र दृष्टिकोण थे। –

2

हालांकि टैग गायब होने के बावजूद, आप मान लेंगे कि आप जावा के बारे में बात कर रहे हैं।

एक "आलसी" समाधान ग्रहण 3.5 के साथ पैक किया जाता है, जो आपके लिए बटन के धक्का पर हैश कोड उत्पन्न करेगा। toString() और बराबर() भी। बहुत अच्छा! मुझे संदेह है कि आप आईडीईए और नेटबीन में समान कार्यक्षमता पा सकते हैं।

इसके अलावा, व्यावहारिक रूप से किसी भी हैश फ़ंक्शन जो लगातार उसी इनपुट के लिए समान मूल्य उत्पन्न करता है। यह (शायद) केवल हैशमैप्स जैसी चीजों की दक्षता को प्रभावित करेगा।

+0

कुछ सामान्य मामलों के लिए, आप सूर्य के जेडीके कोड को देख सकते हैं। अगर मुझे सही याद है, तो स्ट्रिंग्स के लिए यह 37 से गुणा करता है और अगले चरित्र के इंट मान में जोड़ता है। सूचियों के लिए, मुझे लगता है कि यह कुछ समान है, परिणामस्वरूप कुछ प्राइम नंबर और परिणामस्वरूप (या XOR'ing) अगले ऑब्जेक्ट के हैश कोड को जोड़ता है। –

2

यदि आप कस्टम कक्षाओं के लिए हैशकोड को परिभाषित करने के संबंध में बात कर रहे हैं, तो सबसे अच्छा शर्त है कि आप अपने सभी फ़ील्ड हैशकोड फ़ंक्शंस के कुछ प्रकार के गणितीय संयोजन को परिभाषित करें।

हैशकोड को परिभाषित करने में, आपका लक्ष्य आम तौर पर टकराव को कम करने के लिए होता है ताकि यदि आप ऐसा कुछ करते हैं, तो आप आमतौर पर स्पष्ट रूप से स्पष्ट होंगे।

hashcode=(field1.hashcode()*7)+(field2.hashcode()*3)+(field3.hashcode()*51)... 
+0

आपको यह सुनिश्चित करना चाहिए कि गुणक गैर-प्राइम (और विशेष रूप से दो की शक्तियों) की बजाय प्रमुख हैं – AlBlue

+0

यही वह है जो मैं बाद में हूं। क्या संख्याओं के बारे में कुछ जादू है? –

+0

धन्यवाद अलब्लू, गुणक को टकराव की संख्या को कम करने के लिए हमेशा अच्छा और प्राइम होना चाहिए – tinkertime

0

किसी भी प्रबंधित वातावरण में किसी ऑब्जेक्ट हैश फ़ंक्शन का कच्चा कार्यान्वयन स्मृति पता ही होता है।यदि आपको हैश फ़ंक्शन के गुणों की परवाह नहीं है, तो कोई भी मूल्य तब तक करेगा जब तक कि किसी प्रकार का समकक्ष संबंध अलग-अलग उदाहरणों के बीच मौजूद न हो जो समान मान का प्रतिनिधित्व करते हैं।

यदि आप डेटाबेस डेटाबेस के संबंध में परिचित हैं, तो अपनी ऑब्जेक्ट की प्राथमिक कुंजी के बारे में सोचें? प्राथमिक मूल्य प्राथमिक कुंजी का गठन करता है?

कहना है कि यह a, b and c है, ठीक है, तो hashCode अपने क्रियान्वयन की तरह लग रहे हैं इस

return a.hashCode()^b.hashCode()^c.hashCode(); 

^है XOR (अनन्य या) बिट के लिहाज से ऑपरेशन, इस तरह से आप श्रृंखला कर सकते हैं एक साथ मूल्यों के किसी भी संख्या एक हैश मूल्य बनाने के लिए, और अभी भी एक सभ्य फैलाव बनाए रखने के लिए।

+0

"हैश फ़ंक्शन मेमोरी एड्रेस है" - क्या आप इस बारे में निश्चित हैं? जब किसी ऑब्जेक्ट को कॉम्पैक्ट किए जाने पर स्मृति में चारों ओर स्थानांतरित किया जाता है तो क्या होगा? – mfeingold

+0

जितना अधिक उचित रूप से व्यावहारिक है, वर्ग ऑब्जेक्ट द्वारा परिभाषित हैशकोड विधि अलग-अलग वस्तुओं के लिए अलग-अलग पूर्णांक लौटाती है। (आमतौर पर ऑब्जेक्ट के आंतरिक पते को पूर्णांक में परिवर्तित करके कार्यान्वित किया जाता है, लेकिन जावाटीएम प्रोग्रामिंग भाषा द्वारा इस कार्यान्वयन तकनीक की आवश्यकता नहीं होती है।) - http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#h एशकोड% 28% 2 9 –

+0

मैंने जावा दस्तावेज़ों से लिया, यह डिफ़ॉल्ट कार्यान्वयन है और यह उस नए ऑब्जेक्ट() हैशकोड()! = नया ऑब्जेक्ट() हैशकोड() –

0

आपके प्रश्न का उत्तर देने के लिए क्या गलत हो सकता है: आपके फ़ंक्शन द्वारा उत्पन्न हैशकोड का उपयोग आपके वर्ग के उदाहरणों के लिए जगह खोजने के लिए किया जाएगा यदि आप इसे हैशटेबल (शब्दकोश/मानचित्र) में डालते हैं। यदि आपका हैशफंक्शन बहुत से टकराव उत्पन्न करता है, तो आपके हैशटेबल का प्रदर्शन ओ (एन) जितना खराब हो सकता है।

public static int CombineHashCodes(params int[] hashCodes) 
{ 
    unchecked 
    { 
     var result = 0; 
     foreach (var hash in hashCodes) 
      result = (result * 397)^hash; 
     return result; 
    } 
} 

सहज ज्ञान युक्त तर्क है कि संयोजन पहलू XOR ऑपरेटर है:

1

यह एक हैश कोड के संयोजन समारोह है कि मैं का उपयोग करें (सी # में) है। इस प्रकार .NET 4 टुपल्स के लिए करता है:

public static int CombineHashCodes(int h1, int h2) 
{ 
    return ((h1 << 5) + h1)^h2; 
} 
संबंधित मुद्दे