एक ArrayList के सम्‍मिलित () विधि वस्‍तुओं का मूल्‍यांकन कैसे करती है?


303

कहते हैं, मैं एक वस्तु बनाता हूं और उसे अपने साथ जोड़ता हूं ArrayList। अगर मैं फिर उसी कंस्ट्रक्टर इनपुट के साथ एक और ऑब्जेक्ट बनाता हूं, तो क्या contains()विधि दो वस्तुओं के समान होने का मूल्यांकन करेगी ? मान लें कि कंस्ट्रक्टर इनपुट के साथ कुछ भी अजीब नहीं करता है, और दोनों ऑब्जेक्ट्स में संग्रहीत चर समान हैं।

ArrayList<Thing> basket = new ArrayList<Thing>();  
Thing thing = new Thing(100);  
basket.add(thing);  
Thing another = new Thing(100);  
basket.contains(another); // true or false?

class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    equals (Thing x) {
        if (x.value == value) return true;
        return false;
    }
}

क्या वापसी के classलिए इसे लागू किया जाना चाहिए ?contains()true

जवाबों:


339

implementsसूची इंटरफ़ेस ArrayList ।

यदि आप इस विधि के लिए JavadocListcontains को देखते हैं तो आप देखेंगे कि यह equals()मूल्यांकन करने के लिए विधि का उपयोग करता है कि क्या दो वस्तुएं समान हैं।


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

34
यह एक सही उत्तर है, लेकिन ध्यान दें कि आपको एक के Objectबजाय स्वीकार करने के लिए अपनी बराबरी के तरीके को बदलने की आवश्यकता है Thing। यदि आप नहीं करते हैं, तो आपके समान विधि का उपयोग नहीं किया जाएगा। :)
mdierker

1
बस अपने लिए खोजा गया है कि स्रोत मेनू के तहत ग्रहण में "जेनरेट हैशकोड () और बराबर" है।
वलोडिमिर क्रुपच

यह शीर्षक में प्रश्न का उत्तर देता है, लेकिन विवरण में प्रश्न नहीं है, अर्थात "यदि मैं फिर एक ही निर्माता इनपुट के साथ एक और वस्तु बनाता हूं, तो क्या इसमें () विधि दो वस्तुओं के समान होने का मूल्यांकन करेगी?"
रोबगिननेस

3
Collectionsअपने सामान को एक अनुकूलित तरीके से करें, जिसका अर्थ है कि contains()सबसे पहले hashCodeदो वस्तुओं की जांच करता है , और उसके बाद ही कॉल करता है equals()। यदि hashCodeएस अलग हैं (जो हमेशा दो अलग-अलग उदाहरणों के लिए मामला है Thing), तो equals()विधि को नहीं बुलाया जाएगा। अंगूठे के एक नियम के रूप में, जब आप ओवरराइड करते हैं, तो आपको ओवरराइड equals()करना भी नहीं भूलना चाहिए hashCode()
सेवस्तन सवणुक

52

मुझे लगता है कि सही क्रियान्वयन होना चाहिए

public class Thing
{
    public int value;  

    public Thing (int x)
    {
        this.value = x;
    }

    @Override
    public boolean equals(Object object)
    {
        boolean sameSame = false;

        if (object != null && object instanceof Thing)
        {
            sameSame = this.value == ((Thing) object).value;
        }

        return sameSame;
    }
}

1
ifकथन अनावश्यक है। instanceofपर्याप्त है।
पॉल

@Paul आप जिस वक्तव्य के बारे में बात कर रहे हैं, वह कौन सा हिस्सा है?
क्रिस्टोफेसीवीबी

4
object != nullक्योंकि हालत, अनावश्यक है object instanceof Thingवस्तु नहीं होने के लिए जाँच करता है भी शून्य।
अलेक्जेंडर फारबर

15

ArrayList वर्ग (आपके मामले थिंग क्लास) में लागू बराबरी की विधि का उपयोग बराबरी की तुलना करने के लिए करता है।


12

आम तौर पर आपको hashCode()हर बार ओवरराइड करने पर भी ओवरराइड करना चाहिए equals(), भले ही प्रदर्शन को बढ़ावा मिले। HashCode()यह तय करता है कि तुलना करते समय आपकी वस्तु किस 'बकेट' में छंट जाती है, इसलिए जो भी दो वस्तुएं equal()सत्य का मूल्यांकन करती हैं, उन्हें वापस लौटना चाहिए hashCode value()। मुझे इसका डिफ़ॉल्ट व्यवहार याद नहीं है hashCode()(यदि यह 0 देता है तो आपका कोड काम करना चाहिए लेकिन धीरे-धीरे, लेकिन यदि यह पता लौटाता है तो आपका कोड विफल हो जाएगा)। मुझे कई बार याद है कि जब मेरा कोड विफल हो गया था क्योंकि मैं ओवरराइड करना भूल गया था hashCode()। :)


7

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


6
class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    equals (Thing x) {
        if (x.value == value) return true;
        return false;
    }
}

आपको लिखना होगा:

class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    public boolean equals (Object o) {
    Thing x = (Thing) o;
        if (x.value == value) return true;
        return false;
    }
}

अब यह काम कर रहा है ;)


6
आपको थिंग एक्स = (थिंग) ओ नहीं करना चाहिए; पहली जांच के बिना अगर दूसरी वस्तु अशक्त है
स्टील्सक

5

बस यह नोट करना चाहता था कि जब valueआदिम प्रकार नहीं है तो निम्नलिखित कार्यान्वयन गलत है:

public class Thing
{
    public Object value;  

    public Thing (Object x)
    {
        this.value = x;
    }

    @Override
    public boolean equals(Object object)
    {
        boolean sameSame = false;

        if (object != null && object instanceof Thing)
        {
            sameSame = this.value == ((Thing) object).value;
        }

        return sameSame;
    }
}

उस मामले में मैं निम्नलिखित प्रस्ताव करता हूं:

public class Thing {
    public Object value;  

    public Thing (Object x) {
        value = x;
    }

    @Override
    public boolean equals(Object object) {

        if (object != null && object instanceof Thing) {
            Thing thing = (Thing) object;
            if (value == null) {
                return (thing.value == null);
            }
            else {
                return value.equals(thing.value);
            }
        }

        return false;
    }
}

डुप्लिकेट को समाप्त करते समय इसे कैसे लागू करें?
सुजय १३'१६ को

4

अन्य पोस्टरों ने इस सवाल को संबोधित किया है कि कैसे () काम करता है।

आपके प्रश्न का एक समान रूप से महत्वपूर्ण पहलू यह है कि बराबरी को कैसे ठीक से लागू किया जाए। और इसका उत्तर वास्तव में इस बात पर निर्भर करता है कि इस विशेष वर्ग के लिए वस्तु समानता क्या है। आपके द्वारा दिए गए उदाहरण में, यदि आपके पास दो अलग-अलग ऑब्जेक्ट हैं जो दोनों में x = 5 है, तो क्या वे समान हैं? यह वास्तव में इस बात पर निर्भर करता है कि आप क्या करने की कोशिश कर रहे हैं।

यदि आप केवल वस्तु समानता में रुचि रखते हैं, तो ए असमानता () (ऑब्जेक्ट द्वारा प्रदान की गई) का डिफ़ॉल्ट कार्यान्वयन केवल पहचान का उपयोग करता है (यानी यह == अन्य)। यदि आप चाहते हैं, तो बस अपनी कक्षा पर समान () को लागू न करें (इसे ऑब्जेक्ट से विरासत में दें)। आपके द्वारा लिखा गया कोड, जब आप पहचान के लिए जा रहे हैं तो सही है, कभी भी वास्तविक श्रेणी b / c में नहीं दिखाई देगा, यह डिफ़ॉल्ट Object.equals () कार्यान्वयन का उपयोग करने पर कोई लाभ नहीं प्रदान करता है।

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


अपने उद्देश्य के लिए मैं यह देखने की कोशिश कर रहा था कि क्या ArrayList में समान मूल्य की कोई वस्तु थी। मुझे लगता है कि यह एक तरह का हैक है। पुस्तक अनुशंसा के लिए धन्यवाद
मंत्र विदुतिस

3

JavaDoc से शॉर्टकट :

बूलियन होता है (ऑब्जेक्ट ओ)

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.