2009-01-14 17 views
10

-hash के लिए दस्तावेज़ कहते हैं, जबकि एक परिवर्तनशील वस्तु एक संग्रह में संग्रहीत किया जाता है, और इसी प्रकार -isEqual: के लिए दस्तावेज़ कहते हैं -hash मूल्य बराबर वस्तुओं के लिए ही होना चाहिए इसे बदल नहीं करना चाहिए।तकनीक वस्तुओं

यह देखते हुए, क्या किसी को -hash को लागू करने के सर्वोत्तम तरीके के लिए कोई सुझाव है, जैसे कि यह दोनों स्थितियों को पूरा करता है और फिर भी वास्तव में समझदारी से गणना की जाती है (यानी 0 वापस नहीं आती)? क्या कोई जानता है कि फ्रेमवर्क-प्रदान किए गए वर्गों के उत्परिवर्तनीय संस्करण कैसे करते हैं?

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

संपादित करें: मैं यहाँ सोच रहा हूँ कि क्या यह 2 ठेके बनाए रखने के लिए संभव है (जहां बराबर वस्तुओं बराबर हैश है, और जब तक वस्तु एक संग्रह में है हैश में परिवर्तन नहीं करते) जब मैं आंतरिक परिवर्तनशील रहा हूँ वस्तु की स्थिति। मेरा झुकाव "नहीं" कहना है, जब तक कि मैं हमेशा बेवकूफ कुछ नहीं करता जैसे हमेशा हैश के लिए 0 लौटाता हूं, लेकिन यही कारण है कि मैं यह सवाल पूछ रहा हूं।

+0

अनुमान लगाएं कि यह एक पुराना सवाल है, बस इसे मिला ... लेकिन आमतौर पर प्रतिलिपि बनाई गई संग्रह में कुंजियों के रूप में उपयोग की जाने वाली म्यूटेबल ऑब्जेक्ट्स नहीं हैं? क्या वह समस्या को दूर नहीं करता है? – nielsbot

+0

@nielsbot: NSDories के लिए केवल कुंजी कॉपी की गई हैं। एनएसएससेट अपनी ऑब्जेक्ट्स की प्रतिलिपि नहीं बनाता है, और 'CFDictionarySetValue() 'API एपीआई अपनी चाबियाँ कॉपी नहीं करता है। –

+0

'CFDictionarySetValue' करता है अगर आप' CFCCreate' को 'kCFTypeDictionaryKeyCallbacks' पास करते हैं, नहीं? दस्तावेज़ लगभग गैर-संवेदनात्मक हैं ... मुझे लगता है कि एक उत्परिवर्तनीय संग्रह obj सकता है, ओह, हैश मानों को कैश कर सकता है, जो एक संग्रह में एक परिवर्तनीय obj मानने के समान है, अपने हैश को नहीं बदलेगा, है ना? – nielsbot

उत्तर

2

दिलचस्प सवाल है, लेकिन मुझे लगता है कि क्या आप चाहते हैं तार्किक असंभव है। मान लें कि आप 2 ऑब्जेक्ट्स, ए और बी से शुरू करते हैं। वे दोनों अलग हैं, और वे विभिन्न हैश कोड से शुरू होते हैं। आप दोनों हैश टेबल में जोड़ते हैं। अब, आप ए को म्यूट करना चाहते हैं, लेकिन आप हैश कोड नहीं बदल सकते क्योंकि यह पहले से ही टेबल में है। हालांकि, ए को इस तरह से बदलना संभव है कि यह .equals() बी

  1. बदलें बराबर B.hashcode, जो हैश कोड में बदलाव नहीं करते हुए एक हैश तालिका में की बाधा का उल्लंघन करता है के लिए एक की hashCode:

    इस मामले में, आप 2 विकल्प हैं, जिनमें से न तो काम करता है।

  2. हैशकोड को न बदलें, इस मामले में एक्वल्स (बी) लेकिन उनके पास समान हैशकोड नहीं हैं।

ऐसा लगता है कि हैशकोड के रूप में निरंतर उपयोग किए बिना ऐसा करने का कोई संभावित तरीका नहीं है।

+0

को बनाने के लिए प्रश्न अपडेट करूंगा जैसा मैंने सोचा था, और मुझे लगता है कि यह शायद सही है। –

-2

जावा में, अधिकांश उत्परिवर्तनीय कक्षाएं Object.hashCode() को ओवरराइड नहीं करती हैं ताकि डिफ़ॉल्ट कार्यान्वयन उस मान को वापस कर देता है जो ऑब्जेक्ट के पते पर आधारित होता है और नहीं बदलता है। यह सिर्फ उद्देश्य सी के साथ एक ही हो सकता है

+2

सिवाय इसके कि उस नियम का उल्लंघन करता है जो समान वस्तुओं को समान हैश रखने की आवश्यकता है। -इस एक्वाल के लिए डिफ़ॉल्ट कार्यान्वयन: बस पॉइंटर्स की तुलना करता है, लेकिन मैं ऑब्जेक्ट में फ़ील्ड की मान-आधारित तुलना करने के लिए इसे ओवरराइड कर रहा हूं। –

2

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

NSObject documentation for hash से सीधे शब्दों में:

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

(जोर मेरा।)

+0

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

+0

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

+0

प्रश्न को दोबारा पढ़ने पर: क्या आप पूछ रहे हैं कि हैश रखने के लिए कोई तरीका है और क्या है: संग्रह में ऑब्जेक्ट को म्यूट करते समय अनुबंध, या सिर्फ अनुबंध को सामान्य रूप से रखना संभव है या नहीं? मैं दूसरे प्रश्न का जवाब दे रहा था, जो आप नहीं पूछ रहे थे। –

0

चूंकि आप पहले ही ओवरराइड कर रहे हैं -इस एक्वाल: मूल्य-आधारित तुलना करने के लिए, क्या आप वाकई वाकई परेशान होने की ज़रूरत है?

मुझे अनुमान नहीं लगाया जा सकता है कि आपको वास्तव में क्या चाहिए, लेकिन यदि आप अपेक्षित कार्यान्वयन से विचलित किए बिना मूल्य-आधारित तुलना करना चाहते हैं- IEEqual: केवल हेशे को समान रूप से वापस करने के लिए, एक बेहतर दृष्टिकोण NSString की -इस एक्वालटॉस्ट्रिंग की नकल करने के लिए हो सकता है: इसलिए अपना स्वयं का बनाने के लिए - IEqualToFoo: उपयोग करने या ओवरराइड करने के बजाय विधि -इस एक्वाल:।

+1

इस के लिए एनएसओब्जेक्ट प्रोटोकॉल दस्तावेज़ स्पष्ट रूप से बताते हैं कि ओवरराइडिंग --इस एक्वाल: और नहीं -शैश गलत है, और जब संग्रह में क्लास का एक उदाहरण संग्रहित होता है तो समस्याएं उत्पन्न हो सकती हैं। इसके अलावा, एनएसएसटींग ओवरराइड -इस एक्वाल: कॉल करने के लिए- IqualToString: यदि दोनों ऑब्जेक्ट स्ट्रिंग हैं। यह ऐप्पल दस्तावेज़ देखें: http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple%5Fref/doc/uid/TP40002974-CH4-SW25 –

1

यहां सवाल यह नहीं है कि इन दोनों आवश्यकताओं को पूरा कैसे किया जाए, बल्कि मिलना चाहिए। ऐप्पल के दस्तावेज में, यह स्पष्ट रूप से कहा गया है कि:

एक उत्परिवर्तनीय शब्दकोश एक हैश तालिका में रखा जा सकता है लेकिन आपको वहां होने पर इसे बदलना नहीं चाहिए।

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

बस मेरा जवाब पूरा करने के लिए, मैं एक अच्छे हैश कार्यान्वयन का एक उदाहरण दूंगा। आइए मान लें कि आप बनाए गए संग्रह पर -hash के कार्यान्वयन को लिख रहे हैं। यह संग्रह NSObjects को पॉइंटर्स के रूप में संग्रहीत करता है। चूंकि सभी NSObjects हैश समारोह को लागू, आप संग्रह के हैश की गणना में उनके हैश का उपयोग कर सकते हैं:

- (NSUInteger)hash { 
    NSUInteger theHash = 0; 
    for (NSObject * aPtr in self) { // fast enumeration 
     theHash ^= [aPtr hash]; 
    } 
    return theHash; 
} 

इस तरह, दो संग्रह वस्तुओं एक ही संकेत (उसी क्रम में) युक्त एक ही हैश होगा।

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