2009-06-12 11 views
8

मेरे पास जावा में एक ऐरेलिस्ट है जो एक प्रकार से बना है जिसमें दो तार और एक पूर्णांक है। मैं सफलतापूर्वक परीक्षण कर सकता हूं कि इस ArrayList का एक तत्व दूसरे के बराबर है लेकिन मुझे लगता है कि इसमें विधि विफल हो गई है। मेरा मानना ​​है कि यह इस तथ्य के कारण है कि मेरा प्रकार आदिम नहीं है।जावा में एक ऐरेलिस्ट में उपयोग करने का सबसे अच्छा तरीका है?

अब मैं इस के लिए दो विकल्प देख सकते हैं और मुझे आश्चर्य है कि जो सबसे अच्छा विकल्प है:

  1. लागू करने के लिए अपने ही एक मैं कर रहा हूँ के खिलाफ ArrayList के माध्यम से पुनरावृत्ति और प्रत्येक तत्व की समानता के परीक्षण से विधि में शामिल है लूप तोड़ने और फिर तोड़ने के लिए।

  2. या मेरे प्रकार के हैश मैप का उपयोग एरेरलिस्ट के बजाय मूल्य के रूप में पूर्णांक के साथ कुंजी के रूप में करें। यहां मैं हैश मैप में कोई तत्व पहले से मौजूद है या नहीं, यह जांचने के लिए विधि शामिल है।

# 2 के दृष्टिकोण के साथ एकमात्र चेतावनी यह है कि मेरे मामले में मूल्य काफी हद तक अनावश्यक है।

+1

ArrayList के लिए स्रोत कोड देखें और आप देखेंगे कि कार्यान्वयन पहले से ही काफी सरल है। – iny

उत्तर

24

सबसे अधिक संभावना है कि आप आसानी से equals() और hashCode() को अपने प्रकार में ओवरराइड करना भूल गए हैं। equals() क्या के लिए जाँच करता है।

Javadoc से

:

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

संदर्भ समानता के लिए equals परीक्षणों के डिफ़ॉल्ट कार्यान्वयन के बाद से, यह इस तरह के कस्टम डेटा प्रकारों के लिए उपयुक्त नहीं है।

(। और अगर आप equals और hashCode ओवरराइड नहीं किया था, एक HashMap में कुंजी के रूप में अपने प्रकार का उपयोग कर समान रूप से व्यर्थ होगा)


संपादित करें: ध्यान दें कि ओवरराइड करने के लिए, आपको वह सटीक हस्ताक्षर।

class MyDataType { 
    public boolean equals(MyDataType other) { // WRONG! 
     ... 
    } 
    public boolean equals(Object other) { // Right! 
     ... 
    } 
} 

@Override एनोटेशन का उपयोग करने के लिए यह एक बहुत ही मजबूत तर्क है; @Override के साथ एनोटेटेड होने पर पहला उदाहरण संकलित समय पर विफल रहा होगा।

+0

मेरी कक्षा में मैं निर्दिष्ट किया है एक के बराबर होती है विधि:।। निजी बूलियन बराबर (HierarchicalTreemapElement hte) { अगर ((this.getChild() बराबर (hte.getChild()) && (this.getParent() बराबर (hte.getParent()) &&(this.getQuantity() == (hte.getQuantity())))) { सत्य वापस आना; } अन्य { झूठी वापसी; } } लेकिन यदि सरणीसूची का उपयोग किया जाता है तो अभी भी विफल रहता है। हैशकोड के लिए मुझे क्या चाहिए? –

+3

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

+1

हैशकोड के लिए, यदि आप इसे पहले ही ओवरराइड कर चुके हैं, तो शायद यह पर्याप्त है। यदि आपने नहीं किया है, तो आपको निश्चित रूप से करना चाहिए; ओवरराइडिंग बराबर() * हमेशा * हैशकोड() को ओवरराइड करना चाहिए। –

3

क्या आपने बराबर विधि को ओवरराइड किया था? यह सही ढंग से काम करने के लिए आवश्यक है।

0

शायद इसके बजाय इंटेगर क्लास का उपयोग करें? तो आप ऑब्जेक्ट तुलना

14

मेरा अनुमान है कि आपने केवल बराबर टाइप (ऑब्जेक्ट) को ओवरराइड करने के बजाय "दृढ़ता से टाइप किया गया" बराबर विधि लिखा है।दूसरे शब्दों में, आप मिल गया है, तो:

public boolean equals(Foo f) 

आप

public boolean equals(Object o) 

जरूरत है और साथ ही Object.equals ओवरराइड करने के लिए।

कि के साथ "फिट काम करता है के बराबर होती है लेकिन होता है क्योंकि आपके परीक्षण शायद दृढ़ता से टाइप बराबरी फोन नहीं है, लेकिन ArrayList नहीं करता है।

+0

'अपने परीक्षण पास करता है लेकिन विफल रहता है' पर विस्तार करने के लिए, ध्यान दें कि यदि आप MyClass # बराबर का परीक्षण कर रहे हैं, तो आपको ऑब्जेक्ट को पास करने के दौरान ऑब्जेक्ट # बराबर के खिलाफ कॉल का उपयोग करके इसे करना चाहिए। (अपने यूनिट परीक्षणों को ठीक करने के लिए एक नोट बनाता है, क्योंकि वह सोचता है कि वह यह सही नहीं कर रहा है)। –

+0

हम्म ... मुझे यकीन नहीं है कि मेरा जवाब वास्तव में mmyers द्वारा उत्तर में कुछ भी जोड़ता है। Tetsujin नो Oni: क्या आप अपनी टिप्पणी को उस उत्तर पर कॉपी करना चाहते हैं, और फिर मैं इसे हटा सकता हूं? –

2

याद रखें कि यदि आप बराबर ओवरराइड नहीं करें() विधि , तो आपके प्रकार की दो वस्तुएं केवल तभी बराबर होती हैं जब वे उस ऑब्जेक्ट के समान उदाहरण हैं। ArrayList क्लास इस विधि का उपयोग यह जांचने के लिए करती है कि इसमें दिया गया ऑब्जेक्ट है। इसके अलावा, आपको हस्ताक्षर से बिल्कुल मेल खाना चाहिए, जिसका अर्थ है कि इसे ऑब्जेक्ट को पैरामीटर के रूप में लेना चाहिए, न कि Foo।

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

मेरी सिफारिश यह जांचना है कि आप वास्तव में बराबर() और हैशकोड() को ओवरराइड करते हैं और उनके हस्ताक्षर ऑब्जेक्ट क्लास में से मेल खाते हैं।

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