2010-05-27 25 views
5

मुझे कभी भी हैश टेबल में ऑब्जेक्ट्स स्टोर करने की आवश्यकता नहीं है। कारण दो गुना है:यदि मैंने कभी भी हैशसेट का उपयोग नहीं किया है, तो क्या मुझे अभी भी GetHashCode लागू करना चाहिए?

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

दूसरी तरफ बराबर() ऑपरेशन अक्सर उपयोग किया जाता है।

इसलिए मुझे आश्चर्य है कि बराबर फ़ंक्शन को लागू करते समय GetHashCode (जिसे मुझे कभी आवश्यकता नहीं है) को कार्यान्वित करना आवश्यक है (जिसे मुझे अक्सर आवश्यकता होती है)?

+0

अध्याय 9 * (यदि आपके पास पहले से है) में अध्याय 9 * अच्छी तरह से तैयार प्रकार * में एक नज़र डालें और आपको पता चलेगा कि इसे कब ओवरराइड करना है। – Oliver

उत्तर

13

मेरी सलाह - यदि आप इसका उपयोग नहीं करना चाहते हैं, ओवरराइड करें यह और throw new NotImplementedException(); ताकि आप देखेंगे कि आपको इसकी आवश्यकता कहां है।

+1

यह एक बहुत अच्छा विचार है। मुझे आश्चर्य है कि क्यों डिफ़ॉल्ट कार्यान्वयन ऐसा नहीं करता है! –

+2

@ डिमिट्री: क्योंकि डिफ़ॉल्ट कार्यान्वयन संदर्भ पहचान के लिए है, जो कई मामलों में पर्याप्त है। –

+1

ठीक है, आप 'ऑब्जेक्ट' को एक कुंजी के रूप में उपयोग कर सकते हैं, आपके द्वारा बनाए गए प्रत्येक 'ऑब्जेक्ट' को डिफ़ॉल्ट रूप से अनूठा होगा: 'var key = new object();', लेकिन निश्चित रूप से वे हल कर सकते हैं कि केवल एक नया बनाकर जिस वर्ग का आप उपयोग करते हैं, जैसे 'हैशकी', जो अतिरिक्त विधियों के साथ 'ऑब्जेक्ट' है। इसके अतिरिक्त, प्रत्येक ऑब्जेक्ट को स्वयं के द्वारा एक कुंजी के रूप में उपयोग किया जा सकता है, भले ही एक ही सामग्री वाले दो ऑब्जेक्ट्स बराबर नहीं मानते हैं, ताकि आप उन्हें संबंधित ऑब्जेक्ट्स खोजने के लिए लुकअप टेबल में कुंजियों के रूप में उपयोग कर सकें। –

2

आपको इसे लागू करने की आवश्यकता नहीं है। यदि आप अपनी खुद की इक्वाल्स() विधि लिखते हैं तो मैं कुछ GetHashCode कार्यान्वयन का उपयोग करने की अनुशंसा करता हूं जो हैशसेट को तोड़ नहीं देता है। उदाहरण के लिए आप एक स्थिर मूल्य (आमतौर पर 42) वापस कर सकते हैं। हैशसेट प्रदर्शन नाटकीय रूप से घट जाएगा, लेकिन कम से कम यह अभी भी काम करेगा - आपको कभी पता नहीं चलेगा कि भविष्य में कौन सा कोड उपयोग/संपादित/बनाए रखेगा। (संपादित करें: आप एक चेतावनी लॉग इन करने की है, तो इस तरह के एक वर्ग जल्दी हाजिर प्रदर्शन की समस्याओं के लिए एक टुकड़े किए गए संरचना में प्रयोग किया जाता है चाहते हो सकता है)

संपादित करें: केवल अपने गुणों के हैश कोड गठबंधन करने के लिए XOR का उपयोग नहीं करते

यह पहले से ही दूसरों द्वारा कहा जा चुका है कि आप बस अपनी सभी संपत्तियों के हैश कोड जोड़ सकते हैं। केवल एक्सओआर का उपयोग करने के बजाय मैं परिणाम गुणा करने के लिए प्रोत्साहित करता हूं। यदि दोनों मान बराबर हैं (उदा। 0xA^0xA == 0x0) तो XOR का परिणाम 0 मान हो सकता है। इसे 0xA * 0xA, 0xA * 31 + 0xA या 0xA^(0xA * 31) का उपयोग करके आसानी से सुधार किया जा सकता है।

फिर भी, मेरे उत्तर का इरादा यह है कि किसी भी हैश फ़ंक्शन एक से बेहतर है जो बराबर के अनुरूप नहीं है - भले ही यह केवल स्थिर मान देता है। बस गुणों के किसी भी सबसेट का चयन करें (किसी से भी नहीं) आप समानता के लिए उपयोग करते हैं और परिणामों को एक साथ फेंक देते हैं। हैश कोड के लिए गुणों का चयन करते समय, उन छोटे सबसेट्स को पसंद करते हैं जो संयोजन बहुत ही अद्वितीय हैं (उदाहरण के लिए पहला नाम, अंतिम नाम, जन्मदिन - पूरा पता जोड़ने की कोई आवश्यकता नहीं)

+1

+1 लौटने के लिए 42 – Rubys

+0

@ रूबी कोई आश्चर्य नहीं है, वास्तव में :) – sfussenegger

+0

या यहां तक ​​कि घटक चर के हैशकोड XOR'ing भी बहुत आसान है और एक उचित अच्छा वितरण प्रदान करता है। जैसा कि आपने कहा था कि आपको जरूरी नहीं कि एक कठिन कार्यान्वयन का उपयोग करना पड़े। –

3

यदि आप Dictionary या SortedList का उपयोग करते हैं, और Equals ओवरराइड करते हैं, तो आपको हैश फ़ंक्शन होना चाहिए, अन्यथा वे टूट जाएंगे। Equals का उपयोग बीसीएल में पूरे स्थान पर भी किया जाता है, और यदि कोई और आपकी वस्तुओं का उपयोग करता है तो वे GetHashCode की समझदारी से व्यवहार करने की अपेक्षा करेंगे।

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

1

एक पर्याप्त हैश फंक्शन के साथ आ रहा है नहीं मुश्किल है। अक्सर, सभी क्षेत्रों के GetHashCode() से परिणामों का एक साधारण एक्सओआर पर्याप्त है।

+1

एक्सओआर खराब है यदि गुणों के हैश कोड बराबर हैं, यानी यदि गुण स्वयं बराबर हैं। XORing से पहले primes के साथ परिणामों को गुणा करना समस्या को कम करता है, उदा। 'हैश = (हैश 1 * 31)^हैश 2' – sfussenegger

5

मुझे लगता है कि यदि आप मानते हैं कि सख्त आदेश भविष्यवाणी को लागू करना हैश फ़ंक्शन की तुलना में लागू करना बहुत आसान है - इसे बड़ी संख्या में किनारे के मामलों (शून्य मान, वर्ग पदानुक्रम) को संभालने की आवश्यकता है। और हैश फ़ंक्शन aren't that difficult, वास्तव में।

1

यदि आप बराबर ओवरराइड करते हैं तो आपको एमएसडीएन से गेटहाशकोड() को ओवरराइड करना चाहिए: "यह अनुशंसा की जाती है कि इक्विल्स ओवरराइड करने वाली कोई भी कक्षा System.Object.GetHashCode को ओवरराइड करें।" http://msdn.microsoft.com/en-us/library/ms173147.aspx

दो कार्यों को इस अर्थ में मेल खाना चाहिए कि यदि दो वस्तुएं बराबर हैं तो उनके पास एक ही हैश मान होना चाहिए। इसका मतलब यह नहीं है कि यदि दो वस्तुओं में एक ही हैश है तो वे बराबर होना चाहिए। आपको अत्यधिक जटिल हैश एल्गोरिदम की आवश्यकता नहीं है लेकिन इसे पूर्णांक स्थान पर अच्छी तरह वितरित करने का प्रयास करना चाहिए।

4

एक एवीएल पेड़ हैशटेबल से बहुत धीमा होगा। यदि आप केवल कुछ वस्तुओं से निपट रहे हैं तो यह एक मुद्दा नहीं होगा। हैशटेबल्स में ओ (1) आवेषण, हटाए गए और खोज हैं, लेकिन एक एवीएल पेड़ में ओ (लॉग (एन)) ऑपरेशन है।

मैं आगे बढ़ता हूं और दो कारणों से GetHashCode और Equals ओवरराइड करता हूं।

  • यह वास्तव में एक छोटे एक्सओआर कार्यान्वयन का उपयोग करके सभ्य वितरण प्राप्त करना मुश्किल नहीं है।
  • यदि आपकी कक्षाएं सार्वजनिक एपीआई का हिस्सा हैं तो कोई और उन्हें हैशटेबल में स्टोर करना चाहता है।

इसके अलावा, मुझे बीएसटी की पसंद पर सवाल उठाना है। एवीएल पेड़ इन दिनों की शैली से बाहर हैं। ऐसे कई और आधुनिक बीएसटी हैं जो कार्यान्वित करने के लिए आसान हैं और साथ ही साथ काम करते हैं (कभी-कभी बेहतर)। यदि आपको वास्तव में डेटा संरचना की आवश्यकता है जो ऑर्डरिंग बनाए रखता है तो इन विकल्पों पर विचार करें।


XOR रणनीति एक सूक्ष्म संबद्धता समस्या यह है कि a^b = b^a के बाद से कुछ मामलों में टकराव पैदा कर सकता है है। Effective Java का एक समाधान है जिसने पंथ जैसी मान्यता प्राप्त की है जो कि लागू करने के लिए काफी सरल है।

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

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