2008-09-24 14 views
5

जावा में, मेरे पास Java3D कक्षा Point3f का उप-वर्ग Vertex है। अब Point3f इसकी निर्देशांक के मानों के आधार पर equals() की गणना करता है, लेकिन मेरे Vertex कक्षा के लिए मैं कठोर होना चाहता हूं: दो शीर्ष केवल तभी समान होते हैं जब वे एक ही वस्तु हों। अब तक, तो अच्छा:ऑब्जेक्ट के पते से हैशकोड() की गणना कैसे करें?

class Vertex extends Point3f { 

    // ... 

    public boolean equals(Object other) { 
     return this == other; 
    } 
} 

मैं इस equals() के अनुबंध का उल्लंघन करती है, लेकिन जब से मैं केवल एक अन्य कोने करने के लिए कोने की तुलना करेंगे यह एक समस्या नहीं है।

अब, HashMap में शिखर डालने में सक्षम होने के लिए, hashCode() विधि equals() के साथ संगत परिणामों को वापस करनी होगी। यह वर्तमान में ऐसा करता है, लेकिन शायद Point3f के क्षेत्रों में इसके वापसी मूल्य का आधार है, और इसलिए एक ही निर्देशांक के साथ विभिन्न Vertex ऑब्जेक्ट्स के लिए हैश टकराव देगा।

इसलिए मैं Vertex के फ़ील्ड से इसकी गणना करने के बजाय ऑब्जेक्ट के पते पर hashCode() का आधार बनाना चाहता हूं। मुझे पता है कि Object कक्षा यह करती है, लेकिन मैं इसे hashCode() विधि नहीं कह सकता क्योंकि Point3f इसे ओवरराइड करता है।

तो, वास्तव में मेरे सवाल दोहरा है:

  • मैं भी इस तरह के एक उथले equals() चाहते चाहिए?
  • यदि हां, तो, हैश कोड की गणना करने के लिए मैं ऑब्जेक्ट का पता कैसे प्राप्त करूं?

संपादित करें: मैंने बस कुछ सोचा था ... मैं ऑब्जेक्ट सृजन पर एक यादृच्छिक int मान उत्पन्न कर सकता हूं, और हैश कोड के लिए इसका उपयोग कर सकता हूं। क्या यह एक बेहतर तरकीब है? क्यों नहीं)?

उत्तर

10

या तो System.identityHashCode() का उपयोग करें या एक पहचान हैशैप का उपयोग करें।

+0

असल में ... यह वही है जो मुझे चाहिए: डी – Thomas

-2

फ़ंक्शन हैशकोड() ऑब्जेक्ट से विरासत में मिला है और जैसा कि आप चाहते हैं (ऑब्जेक्ट स्तर पर, समन्वय-स्तर पर नहीं) के रूप में कार्य करता है। इसे बदलने की जरूरत नहीं है।

आपके बराबर विधि के लिए, इसका उपयोग करने का कोई कारण नहीं है, क्योंकि आप बराबर का उपयोग करने के बजाय अपने कोड में obj1 == obj2 कर सकते हैं, क्योंकि यह सॉर्टिंग और इसी तरह के लिए है, जहां समन्वय की तुलना करना एक बनाता है बहुत अधिक समझ में आता है।

+0

मेरा कोई नियंत्रण नहीं है कि हैश मैप किस तुलना में उपयोग करता है ... – Thomas

1

System.identityHashCode() दिए गए ऑब्जेक्ट के लिए एक ही हैश कोड देता है क्योंकि डिफ़ॉल्ट विधि hashCode() द्वारा वापस किया जाएगा, चाहे दिया गया ऑब्जेक्ट क्लास hashCode() ओवरराइड करता है या नहीं।

0

आप एक प्रतिनिधि का उपयोग करते हैं भले ही यह answer शायद बेहतर है।


class Vertex extends Point3f{ 
    private final Object equalsDelegate = new Object(); 
    public boolean equals(Object vertex){ 
     if(vertex instanceof Vertex){ 
     return this.equalsDelegate.equals(((Vertex)vertex).equalsDelegate); 
     } 
     else{ 
     return super.equals(vertex); 
     } 
    } 
    public int hashCode(){ 
     return this.equalsDelegate.hashCode(); 
    } 
} 
0

बस FYI करें, आपकी बराबरी विधि बराबर अनुबंध (आधार वस्तु का अनुबंध है कि के लिए) का उल्लंघन नहीं करता ... कि मूल रूप से आधार वस्तु विधि के लिए बराबर विधि है, इसलिए यदि आप चाहते हैं पहचान बजाय बराबर होती है Vertex बराबर है, यह ठीक है।

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

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

कृपया जवाब के रूप में यह स्वीकार नहीं करते हालांकि निश्चित रूप से (आप क्या चुना है और अधिक व्यावहारिक है), मैं बस आप हैश कोड के बारे में कुछ अधिक पृष्ठभूमि की जानकारी देना चाहता था और बराबर होती है ;-)

+0

यह प्वाइंट 3 एफ के कारण अनुबंध का उल्लंघन करता है।बराबर (Vertex) सच हो सकता है, जबकि विपरीत कॉल हमेशा झूठी वापसी होगी। इसलिए, मेरा कार्यान्वयन सममित नहीं है। – Thomas

+0

मुझे यह भी एहसास है कि डिफ़ॉल्ट हैशकोड() मान्य है, लेकिन यह आवश्यक से अधिक कर रहा है। और चूंकि मैं हैशटेबल और हैशसेट का काफी उपयोग करता हूं, मुझे लगा कि यह एक प्रदर्शन जीत होगी। – Thomas

+0

अच्छी तरह से, यह पॉइंट 3 एफ बराबर विधि का उल्लंघन करता है, ऑब्जेक्ट बराबर विधि नहीं है ... जो मैं संदर्भित कर रहा था (और क्या हैश टेबल में दिलचस्पी है) –

0

क्यों क्या आप हैशकोड() को पहले स्थान पर ओवरराइड करना चाहते हैं? यदि आप समानता की किसी अन्य परिभाषा के साथ काम करना चाहते हैं तो आप इसे करना चाहते हैं। उदाहरण के लिए

सार्वजनिक वर्ग ए { int आईडी;

सार्वजनिक बूलियन बराबर (ए अन्य) {वापसी other.id == id} सार्वजनिक पूर्णांक hashCode() {वापसी आईडी;}

} जहां स्पष्ट है कि पहचान-पत्र ही हैं, तो होना चाहते हैं तो वस्तुओं ही हैं, और इतना है कि यदि आप ऐसा नहीं कर सकते हैं hashCode ओवरराइड:

HashSet हैश = नए HashSet(); हैश.एड (नया ए (1)); हैश.एड (नया ए (1)); और 2 समान (समानता की अपनी परिभाषा के दृष्टिकोण से) ए प्राप्त करें। सही व्यवहार तब होगा जब आपके पास हैश में केवल 1 ऑब्जेक्ट होगा, दूसरा लेखन ओवरराइट होगा।

+0

जो भी आप कहते हैं वह सही है, लेकिन मैं आपका बिंदु देखने में विफल रहता हूं। – Thomas

0

चूंकि आप तार्किक तुलना के रूप में बराबर का उपयोग नहीं कर रहे हैं, लेकिन एक भौतिक एक (यानी यह वही वस्तु है), एकमात्र तरीका आप गारंटी देंगे कि हैशकोड एक अद्वितीय मूल्य लौटाएगा, यह आपके बदलाव को लागू करना है खुद का सुझाव यादृच्छिक संख्या उत्पन्न करने के बजाय, प्रत्येक ऑब्जेक्ट के लिए वास्तविक अद्वितीय मान उत्पन्न करने के लिए यूयूआईडी का उपयोग करें।

System.identityHashCode() काम करेंगे, समय की सबसे, लेकिन विधि Object.hashCode() के रूप में इसकी गारंटी नहीं है नहीं हर वस्तु के लिए एक अनूठा मूल्य वापस करने की गारंटी दी है। मैंने मामूली मामला देखा है, और यह शायद वीएम कार्यान्वयन पर निर्भर करेगा, जो ऐसा नहीं है जिसे आप चाहते हैं कि आपका कोड निर्भर हो।

ऑब्जेक्ट.hashCode(): के लिए javadocs से उद्धरण जितना व्यावहारिक रूप से व्यावहारिक है, वर्ग ऑब्जेक्ट द्वारा परिभाषित हैशकोड विधि अलग-अलग वस्तुओं के लिए अलग पूर्णांक लौटाती है। (यह आमतौर पर ऑब्जेक्ट के आंतरिक पते को एक पूर्णांक में परिवर्तित करके कार्यान्वित किया जाता है, लेकिन जावाटीएम प्रोग्रामिंग भाषा द्वारा इस कार्यान्वयन तकनीक की आवश्यकता नहीं होती है।)

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

+0

System.identityHashCode() ठीक है, क्योंकि हैशकोड() अपेक्षित नहीं है * अलग-अलग वस्तुओं के लिए अलग-अलग मान वापस करने के लिए; यह केवल बराबर वस्तुओं के बराबर मूल्य वापस करने की आवश्यकता है। – Thomas

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