[Java] जावा संग्रह क्यों सामान्य तरीकों को हटा नहीं रहे हैं?


Answers

remove() ( Map साथ-साथ Collection ) सामान्य नहीं है क्योंकि आप किसी भी प्रकार की ऑब्जेक्ट को remove() में सक्षम होना चाहिए remove() । हटाई गई ऑब्जेक्ट को उसी ऑब्जेक्ट के समान नहीं होना चाहिए जिसे आप remove() लिए पास करते हैं remove() ; यह केवल इतना आवश्यक है कि वे बराबर हों। remove() के विनिर्देशन से, remove(o) ऑब्जेक्ट को हटा देता है जैसे कि (o==null ? e==null : o.equals(e)) true । ध्यान दें कि o और e को एक ही प्रकार की आवश्यकता नहीं है। यह इस तथ्य से मिलता है कि equals() विधि किसी Object में पैरामीटर के रूप में लेती है, न कि वस्तु के समान ही।

हालांकि, यह आमतौर पर सच हो सकता है कि कई वर्गों ने equals() परिभाषित किया है ताकि इसकी वस्तुएं केवल अपनी कक्षा की वस्तुओं के बराबर हो सकें, जो निश्चित रूप से हमेशा मामला नहीं है। उदाहरण के लिए, List.equals() लिए विनिर्देश कहता है कि दो सूची ऑब्जेक्ट बराबर हैं यदि वे दोनों सूचियां हैं और समान सामग्री हैं, भले ही वे List विभिन्न कार्यान्वयन हों। तो इस प्रश्न में उदाहरण के लिए वापस आना, एक Map<ArrayList, Something> और मेरे लिए एक LinkedList साथ तर्क के रूप में remove() के लिए तर्क के रूप में संभव है, और इसे उसी सामग्री के साथ एक सूची है जो कुंजी को हटा देना चाहिए । यह संभव नहीं होगा अगर remove() सामान्य थे और इसके तर्क प्रकार को प्रतिबंधित कर दिया गया था।

Question

Collection.remove (ऑब्जेक्ट ओ) जेनेरिक क्यों नहीं है?

लगता है कि Collection<E> boolean remove(E o); हो सकता है boolean remove(E o);

फिर, जब आप गलती से निकालने का प्रयास करते हैं (उदाहरण के लिए) Collection<String> से प्रत्येक व्यक्ति स्ट्रिंग के बजाय Set<String> , तो बाद में डीबगिंग समस्या के बजाय यह एक संकलित समय त्रुटि होगी।




अन्य उत्तरों के अलावा, एक और कारण है कि विधि को Object को स्वीकार करना चाहिए, जो भविष्यवाणी करता है। निम्नलिखित नमूने पर विचार करें:

class Person {
    public String name;
    // override equals()
}
class Employee extends Person {
    public String company;
    // override equals()
}
class Developer extends Employee {
    public int yearsOfExperience;
    // override equals()
}

class Test {
    public static void main(String[] args) {
        Collection<? extends Person> people = new ArrayList<Employee>();
        // ...

        // to remove the first employee with a specific name:
        people.remove(new Person(someName1));

        // to remove the first developer that matches some criteria:
        people.remove(new Developer(someName2, someCompany, 10));

        // to remove the first employee who is either
        // a developer or an employee of someCompany:
        people.remove(new Object() {
            public boolean equals(Object employee) {
                return employee instanceof Developer
                    || ((Employee) employee).company.equals(someCompany);
        }});
    }
}

मुद्दा यह है कि remove विधि को पारित करने वाली वस्तु equals विधि को परिभाषित करने के लिए ज़िम्मेदार है। बिल्डिंग भविष्यवाणी इस तरह से बहुत आसान हो जाती है।




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




एक और कारण इंटरफेस की वजह से है। इसे दिखाने के लिए यहां एक उदाहरण दिया गया है:

public interface A {}

public interface B {}

public class MyClass implements A, B {}

public static void main(String[] args) {
   Collection<A> collection = new ArrayList<>();
   MyClass item = new MyClass();
   collection.add(item);  // works fine
   B b = item; // valid
   collection.remove(b); /* It works because the remove method accepts an Object. If it was generic, this would not work */
}