2010-06-02 8 views
8

मेरे पास एक कक्षा है, "Accumulator", जो तुलनात्मक तुलना करने के लिए विधि को लागू करता है, और मैं इन ऑब्जेक्ट्स को हैशसेट में रखने की कोशिश कर रहा हूं।जावा हैशसेट डुप्लिकेट की अनुमति दे रहा है; तुलनीय के साथ समस्या?

जब मैं हैशसेट में() जोड़ता हूं, तो मुझे अपनी तुलना में कोई गतिविधि नहीं दिखाई देती है, डीबगर में विधि, चाहे मैं अपने ब्रेकपॉइंट्स कहां सेट करता हूं। इसके अतिरिक्त, जब मैं add() s के साथ किया जाता हूं, तो मुझे सेट के भीतर कई डुप्लिकेट दिखाई देते हैं।

मैं यहां क्या खराब कर रहा हूं; यह तुलना क्यों नहीं कर रहा है, और इसलिए, डुप्लिकेट की अनुमति है?

धन्यवाद,
आईवीआर Avenger

उत्तर

15

मैं यहाँ क्या खराब कर रहा हूं?

हैशसेट hashCode() पर आधारित है, compareTo() पर नहीं। आप इसे TreeSet से भ्रमित कर सकते हैं। दोनों मामलों में, equals() को इस तरीके से लागू करना सुनिश्चित करें जो अन्य विधि के अनुरूप है।

10

आप सही ढंग से hashCode() और equals() को लागू करने की जरूरत है।

आपको hashCode ओवरराइड करना होगा और अपनी कक्षा में मानों के आधार पर एक नंबर वापस करना होगा, जैसे कि किसी भी दो बराबर वस्तुओं में एक ही हैशकोड है।

+0

बराबर के बराबर होगा, यह पूरी तरह से अमान्य होगा। – Justin

1

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

+1

यदि बराबर ओवरराइड किया गया है तो आपको केवल हैशकोड को ओवरराइड करने की आवश्यकता है (परिभाषा समानता बदल गई है)। दूसरी तरफ जरूरी नहीं है। हैशकोड को 1 लौटने और अकेले बराबर छोड़ने के लिए यह पूरी तरह कानूनी है। –

2

जब हैशकोड 2 ऑब्जेक्ट्स के लिए अलग-अलग मान देता है, तो बराबर उपयोग नहीं किया जाता है। Btw, compareTo संग्रह hashing के साथ कुछ नहीं :) लेकिन क्रमबद्ध संग्रह

2

आपका वस्तुओं Comparable हैं, और शायद आप equals() भी क्रियान्वित किया है, लेकिन वस्तु हैश साथ HashSets सौदा है, और बाधाओं आप hashCode() लागू नहीं किया है कर रहे हैं (या hashCode() अपने क्रियान्वयन की दो वस्तुओं है कि (a.equals(b) == true) हैं के लिए एक ही हैश वापस नहीं करता है।

4

HashSet hashCode() और equals() तरीकों का उपयोग करता जोड़े जाने से डुप्लिकेट को रोकने के लिए। सबसे पहले, यह वस्तु आप करना चाहते हैं हैश कोड हो जाता है जोड़ें। फिर, यह संबंधित बाल्टी टी के लिए मिलता है टोपी हैश कोड और उस बाल्टी में प्रत्येक ऑब्जेक्ट के माध्यम से equals() विधि का उपयोग करके यह देखने के लिए कि सेट में कोई भी समान वस्तुएं मौजूद हैं या नहीं।

आपका डीबगर compareTo() पर तोड़ नहीं रहा है क्योंकि इसका उपयोग कभी भी HashSet के साथ नहीं किया जाता है!

नियम हैं:

  1. दो तो वस्तुओं बराबर, उनके हैश कोड बराबर होना चाहिए रहे हैं तो।

  2. लेकिन अगर दो वस्तुओं 'हैश कोड बराबर हैं, तो यह इसका मतलब यह नहीं करता वस्तुओं बराबर कर रहे हैं!यह हो सकता है कि दोनों ऑब्जेक्ट्स में एक ही हैश होता है।

1

जब कभी आप वर्ग एक्यूमुलेटर की एक वस्तु बनाने यह JVM में नए स्थान लेता है और अद्वितीय hashCode हर बार जब आप HashSet में एक वस्तु को जोड़ने देता है। यह वस्तु के मूल्य पर निर्भर करता है नहीं करता है क्योंकि आप ओवरराइड नहीं है hashCode() विधि इसलिए यह वस्तु कॉल करेंगे वर्ग hashCode() विधि है जो अपने कार्यक्रम में बनाए गए हर वस्तु के साथ अद्वितीय hashCode वापस आ जाएगी।

समाधान:

अवहेलना hashCode() और बराबर() विधि और अपने वर्ग के गुणों के आधार पर अपने तर्क लागू होते हैं। बराबरी और hashCode अनुबंध

http://www.ibm.com/developerworks/java/library/j-jtp05273/index.html

+0

प्रदान किया गया लिंक बहुत उपयोगी है और मेरे जैसे बिनरिन लोगों के लिए यह बहुत उपयोगी है। –

2

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

public bolean equals(Object aSong){ 
    if(!(aSoneg instanceof Song)){ 
     return false; 
    } 
    Song s=(Song) aSong; 
    return getTitle().equals(s.getTitle()); 
    } 

के लिए यू पार कर लेते हैं सांग aSong बजाय वस्तु aSong अपने बराबर विधि लिखना कभी नहीं कहा जाता हो जाएगा।

आशा है कि यह

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