2011-12-16 14 views
7

TreeSet में एक निर्माता है जो एक तुलनित्र लेता है, जिसका अर्थ है कि यदि आपके द्वारा संग्रहीत वस्तुओं Comparable ऑब्जेक्ट्स स्वयं नहीं हैं, तो आप एक कस्टम तुलनित्र प्रदान कर सकते हैं।हैशसेट/हैश मैप (कस्टम हैशर) के लिए ट्रीसेट/ट्रीमैप समतुल्य

क्या कोई गैर-निर्धारित सेट का एक समान कार्यान्वयन है? (जैसे कि एक "क़मी बनाने की मशीन" उद्देश्य यह है कि equals() और hashCode() वस्तुओं टी है कि वस्तुओं के अपने कार्यान्वयन से अलग हो सकता? के लिए गणना करता है लेता है HashSet<T> के लिए एक विकल्प)

सी ++ std::hash_set, तो आप इस देता है बस हो, तो जावा के लिए कुछ सोच ।


संपादित करें: @Max equals() के बारे में एक अच्छा तकनीकी बिंदु को लाता है - निष्पक्ष पर्याप्त; और TreeMap और HashMap कुंजी Map.containsKey() के माध्यम से यह सच है। लेकिन क्या वहां अन्य प्रसिद्ध डेटा संरचनाएं हैं जो कस्टम हैशर्स द्वारा संगठन की अनुमति देती हैं?

+0

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

उत्तर

9

नहीं, "हैशर" ऑब्जेक्ट रखने से Collections विनिर्देशों द्वारा समर्थित नहीं है। आप निश्चित रूप से अपने स्वयं के संग्रह को कार्यान्वित कर सकते हैं जो इसका समर्थन करता है लेकिन ऐसा करने का दूसरा तरीका Hasher पर एक रैपिंग ऑब्जेक्ट होने के लिए है जिसे आप अपने HashSet में स्टोर करते हैं।

Set<HasherWrapper<Foo>> set = new HashSet<HasherWrapper<Foo>>(); 
set.add(new HasherWrapper(foo)); 
... 

आवरण वर्ग तो कुछ ऐसा दिखाई देगा:

private class HasherWrapper<T> { 
    T wrappedObject; 
    public HasherWrapper(T wrappedObject) { 
     this.wrappedObject = wrappedObject; 
    } 
    @Override 
    public int hashCode() { 
     // special hash code calculations go here 
    } 
    @Override 
    public boolean equals(Object obj) { 
     // special equals code calculations go here 
    } 
} 
+1

प्रश्न का अच्छा समाधान। एक सुझाव, आपको 'लपेटा ऑब्जेक्ट' अंतिम बनाना चाहिए। इसके अलावा, 'wrappedObject' एक गेटर के साथ सार्वजनिक या निजी होना चाहिए। –

+0

अंतिम क्यों? क्या वह वास्तव में हॉटस्पॉट के साथ इतना मदद करता है? यह देखते हुए कि यह एक निजी वर्ग है, मैं बाहरी वर्ग को बिना किसी गेटटर के मैदान तक पहुंचने की अनुमति दूंगा। – Gray

+0

कई वेब संदर्भों का कहना है कि इन दिनों अंतिम आवश्यक नहीं है क्योंकि वीएम स्मार्ट हैं और जानते हैं कि कुछ ओवरराइड किया गया है या नहीं। http://stackoverflow.com/questions/4279420/does-use-of-final-keyword-in-java-improve-the-performance – Gray

0

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

+5

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

1

नहीं, विनिर्देशन द्वारा नहीं किया जा सकता है और वहां नहीं हो सकता है। इसके अलावा, आप TreeSet जिस तरह से Comparator का उपयोग करते हैं, उसे गलत समझा।

TreeSet Javadoc से

:

ध्यान दें कि आदेश एक सेट (एक स्पष्ट तुलनित्र प्रदान की जाती है या नहीं) द्वारा बनाए रखा बराबरी के अनुरूप होना चाहिए अगर इसे सही ढंग से सेट इंटरफ़ेस को लागू है। (बराबर के साथ संगत की सटीक परिभाषा के लिए तुलनात्मक या तुलनात्मक देखें।) यह है क्योंकि सेट इंटरफ़ेस को बराबर ऑपरेशन, के संदर्भ में परिभाषित किया गया है लेकिन एक ट्रीसेट उदाहरण तुलना (या तुलना) की तुलना में सभी तत्व तुलना करता है। विधि, इसलिए इस विधि द्वारा 0 तत्वों के बराबर समझा जाता है, सेट के दृष्टिकोण से, बराबर। किसी सेट का व्यवहार अच्छी तरह से परिभाषित किया गया है भले ही उसका ऑर्डर असंगत बराबर हो; यह बस सेट इंटरफ़ेस के सामान्य अनुबंध का पालन करने में विफल रहता है।

Comparable javadoc से

:

एक वर्ग सी के लिए प्राकृतिक आदेश के बराबर होती है के साथ संगत होना कहा जाता है यदि और केवल यदि e1.compareTo (E2) == 0 के रूप में ही बूलियन मान है कक्षा 1 के प्रत्येक ई 1 और ई 2 के लिए e1.equals (e2) ध्यान दें कि शून्य किसी भी वर्ग का उदाहरण नहीं है, और e.compareTo (null) को NullPointerException फेंकना चाहिए, भले ही e.equals (null) झूठी रिटर्न हो।

Collection javadoc से

: अगर इस संग्रह निर्दिष्ट तत्व शामिल

बूलियन (वस्तु ओ)

रिटर्न सच होता है। अधिक औपचारिक रूप से, सही होता है अगर केवल संग्रह में कम से कम एक तत्व ई है (जैसे = o null? e == null: o.equals (e))।

इसलिए, विनिर्देश द्वारा वहाँ कि Collection<E> इंटरफेस और पूरी तरह से ऑब्जेक्ट सम्मिलित करें कुछ बाहरी तुलनाकारी शैली वस्तु पर निर्भर लागू करता वर्ग के किसी भी प्रकार नहीं हो सकता। ऑब्जेक्ट पहले से डाला गया है या नहीं, यह सत्यापित करने के लिए सभी संग्रहों को equalsObject क्लास का उपयोग करना चाहिए।

+0

मैं समझने की कोशिश कर रहा हूं कि आप एक अलग कस्टम तुलनित्र प्रदान नहीं कर सकते हैं जो बराबर के अनुरूप है। E2.compareTo (e1) यह प्राप्त नहीं करता है (यह केवल ऑर्डरिंग को उलट देता है, लेकिन बराबर आइटम अभी भी बराबर हैं)? –

+0

क्योंकि तब संग्रह इंटरफ़ेस का विनिर्देश नामित तुलनाकर्ता के प्रोग्रामर कार्यान्वयन पर निर्भर करेगा। संग्रह इंटरफ़ेस स्पष्ट रूप से बताता है कि ** इसके सभी कार्यान्वयन ** ऑब्जेक्ट्स को समान मानेंगे यदि 'ए।बराबरी (ख) '। यदि आप किसी प्रकार का संग्रह लागू करते हैं जो उस नियम को अनदेखा करता है या आंशिक रूप से अनदेखा करता है (जैसे लेखक निर्दिष्ट किया गया है) - आप संग्रह इंटरफ़ेस के विनिर्देश को तोड़ देंगे। भले ही आप प्रलेखन में लिखते हैं "उत्तीर्ण तुलनित्र ** ** ** बराबर के साथ संगत होना चाहिए !!" - विनिर्देश अभी भी टूटा रहेगा। – bezmax

4

मानक पुस्तकालय में ऐसा कोई कार्यान्वयन नहीं है, लेकिन यह आपको स्वयं को रोल करने से नहीं रोकता है। यह ऐसा कुछ है जिसे मैं अक्सर खुद रखना चाहता था।

कारण के लिए http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4771660 देखें:

हम जटिलता बचना चाहते थे। जब संग्रह ढांचे को डिजाइन किया गया था, तब हमने गंभीरता से इस धारणा का मनोरंजन किया, लेकिन इसे अस्वीकार कर दिया। पावर-टू-वेट राशन कम लग रहा था। हमने महसूस किया कि आप समय के 95% चाहते थे; ==, 4%; और कुछ और 1%। समझदारी थोक संचालन के लिए अनुबंध जब समानता भविष्यवाणी करती है तो बहुत मुश्किल होती है।

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