2011-05-31 14 views
16

विधि Set डेटाटाइप द्वारा उपयोग की जाने वाली विधि को ओवरराइड करने का कोई तरीका है? मैंने Fee नामक कक्षा के लिए एक कस्टम equals विधि लिखा था। अब मेरे पास Fee है और मैं यह सुनिश्चित करना चाहता हूं कि कोई डुप्लीकेट प्रविष्टियां न हों। इस प्रकार मैं SetLinkedList के इंस्टेड का उपयोग करने पर विचार कर रहा हूं, लेकिन Fee कक्षा में ओवरराइड equals विधि में दो फीस बराबर रहता है या नहीं, यह तय करने के मानदंड।जावा सेट संग्रह - ओवरराइड बराबर विधि

एक LinkedList का उपयोग कर रहे हैं, तो मैं हर सूची आइटम से अधिक पुनरावृति और एक पैरामीटर के रूप शेष प्रविष्टियों के साथ Fee वर्ग में ओवरराइड equals विधि कॉल करना होगा। बस इसे अकेले पढ़ना बहुत अधिक प्रसंस्करण की तरह लगता है और कम्प्यूटेशनल जटिलता में जोड़ देगा।

क्या मैं Set का उपयोग ओवरराइड equals विधि से कर सकता हूं? क्या मैं?

उत्तर

3

Set सेट में जोड़े गए ऑब्जेक्ट के बराबर विधि का उपयोग करता है। JavaDoc राज्य

एक संग्रह जिसमें कोई डुप्लिकेट तत्व नहीं है। अधिक औपचारिक रूप से, सेटों में ई 1 और ई 2 तत्वों की कोई जोड़ी नहीं होती है, जैसे e1.equals (e2), और अधिकतर शून्य तत्व पर।

Set.equals() विधि केवल समानता के लिए दो सेटों की तुलना करने के लिए उपयोग की जाती है। यह सेट से आइटम जोड़ने/निकालने के हिस्से के रूप में कभी भी उपयोग नहीं किया जाता है।

-1

वहाँ के रूप में जैफ फोस्टर ने कहा Apache Commons Collection

+1

क्या आप इस बारे में विस्तार से बता सकते हैं कि यह ओपी का जवाब कैसे देता है? मैं ' सेट' के लिए ऊपरी/लोअरकेस को अनदेखा करने का एक तरीका ढूंढ रहा हूं। कंटेनर ("foo") ' –

30

में PredicatedList या PredicatedSet हैं:

Set.equals() विधि केवल समानता के लिए दो सेट की तुलना करने के लिए किया जाता है।

आप उपयोग कर सकते हैं एक Set डुप्लिकेट प्रविष्टियों से छुटकारा पाने के लिए, लेकिन सावधान रहना: HashSet समानता निर्धारित करने के लिए अपने युक्त वस्तुओं की equals() तरीकों का उपयोग नहीं करता है।

एक HashSet एक आंतरिक HashMap<Integer(HashCode), Object> साथ प्रविष्टियों जाता है और बराबरी के() के साथ-साथ हैशकोड की बराबरी विधि समानता निर्धारित करने के लिए उपयोग करता है।

class Fee { 
     String name; 

    public boolean equals(Object o) { 
     return (o instanceof Fee) && ((Fee)o.getName()).equals(this.getName()); 
    } 

    public int hashCode() { 
     return name.hashCode(); 
    } 

} 
+4

ए 'हैशसेट'' सेट 'अनुबंध का पालन करता है जिसके लिए समानता निर्धारित करने के लिए' बराबर() 'विधि का उपयोग करने की आवश्यकता होती है। लेकिन यह इस तथ्य का उपयोग करता है कि 'ऑब्जेक्ट' की आवश्यकता है 'हैशकोड() 'यदि यह बराबर()' अन्य वस्तु है। आप ** एक ही 'हैशकोड' में एक ही 'हैशकोड() 'मान के साथ ** एकाधिक ऑब्जेक्ट्स कर सकते हैं। – Martin

+0

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

6

आप और का उपयोग करना चाहिए कर सकते हैं: इस मुद्दे को हल करने के लिए

एक तरीका यह है कि आप कक्षा सेट में डाल में hashCode() ओवरराइड करने के लिए, ताकि यह आपके equals() मापदंड

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

उदाहरण के लिए:

public Fee{ 

    public String fi; 

    public String fo; 

    public int hashCode(){ 

     return fi.hashCode()^fo.hashCode(); 
    } 

    public boolean equals(Object obj){ 

     return fi.equals(obj.fi) && fo.equals(obj.fo); 
    } 
} 

(आवश्यक के रूप में अशक्त चेक, निश्चित रूप से है।)

सेट अक्सर hashCode() का उपयोग प्रदर्शन का अनुकूलन करने, और यदि आपके hashCode विधि टूट गया है दुर्व्यवहार होगा।

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 

हैश सही ढंग से उत्पन्न नहीं है: उदाहरण के लिए, HashSet uses an internal HashMap.

If you check the source code of HashMap, आप इसे दोनों hashCode() और बराबरी() समानता का निर्धारण करने के तत्वों के तरीके पर निर्भर करता है देखेंगे , आपके बराबर विधि कभी नहीं बुलाया जा सकता है।

अपना सेट तेज़ी से बनाने के लिए, आपको उन वस्तुओं के लिए अलग हैश कोड उत्पन्न करना चाहिए जो कहीं भी संभव नहीं हैं।

+2

मुझे पता है कि यह एक उदाहरण है, लेकिन आपको हैशकोड उत्पन्न करने के लिए concatenation का उपयोग नहीं करना चाहिए। आपको साइड की तरह, हैशकोड विधि को अक्सर कहा जा सकता है, और स्ट्रिंग कॉन्सटेनेशन एक धीमी और महंगी ऑपरेशन है। ऐसा करने का एक बेहतर तरीका बस XOR स्ट्रिंग हैशकोड होगा। उदाहरण के लिए: 'वापसी fi.hashCode()^fo.hashCode(); ' इसके अलावा, आपकी' बराबर()' विधि थोड़ा अधिक मारने वाली है। आपको 'f'' के साथ' fi' की तुलना करने की आवश्यकता नहीं है, और उसके बाद 'fo' की तुलना' f'' से करें। 'ऑब्जेक्ट' जावाडोक यह स्पष्ट करता है कि 'बराबर() 'विधि सममित होना चाहिए। इसलिए, केवल 'fi.equals (fo) निष्पादन पर्याप्त है ('null' को अनदेखा करें)। – Moinonime

+0

धन्यवाद मैथ्यू। मैंने स्ट्रिंग को संयोजित करने के बजाय एक्सओआर को हैश कोड में अपना जवाब संपादित किया। मुझे नहीं लगता कि बराबर विधि के बारे में आपकी टिप्पणी मान्य है हालांकि। fi.equals (fo) पूरी तरह से एक अलग तुलना होगी, और परिभाषित हैशकोड विधि के साथ संगत नहीं है। – SharkAlley

1

एक समाधान एक तुलनात्मक के साथ TreeSet का उपयोग करना होगा।

प्रलेखन से:

TreeSet उदाहरण, अपना compareTo का उपयोग कर सभी तत्व तुलना करता है (या तुलना) विधि है, तो दो तत्वों है कि इस विधि से बराबर माना जाता है सेट, बराबर के दृष्टिकोण से, कर रहे हैं।

यह दृष्टिकोण एक लिंक्डलिस्ट का उपयोग करने से बहुत तेज होगा, लेकिन हैशसेट (एलएन (एन) बनाम एन) से थोड़ा धीमा होगा।

ट्रीसेट का उपयोग करने के एक तरफ प्रभाव को ध्यान में रखना उचित है कि आपका सेट सॉर्ट किया गया है।

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