सूची <इंटेगर> से एक इंटेगर को ठीक से निकालना


201

यहाँ एक अच्छा नुकसान है जिसका मैंने अभी सामना किया है। पूर्णांकों की सूची पर विचार करें:

List<Integer> list = new ArrayList<Integer>();
list.add(5);
list.add(6);
list.add(7);
list.add(1);

निष्पादित होने पर क्या होता है, इस पर कोई शिक्षित अनुमान list.remove(1)? किस बारे में list.remove(new Integer(1))? यह कुछ बुरा कीड़े पैदा कर सकता है।

बीच में अंतर करने का उचित तरीका क्या है remove(int index), जो दिए गए सूचकांक से एक तत्व को हटाता है और remove(Object o), जो पूर्णांकों की सूची से निपटने के दौरान संदर्भ द्वारा एक तत्व को निकालता है?


यहाँ पर विचार करने के लिए मुख्य बिंदु एक @Nikita का उल्लेख किया गया है - सटीक पैरामीटर मिलान ऑटो-बॉक्सिंग पर पूर्वता लेता है।


11
A: यहाँ असली मुद्दा यह है कि सूर्य पर किसी ने किसी तरह आदिम होने के बारे में सोचा था (अपरिवर्तनीय) रैपर कक्षाएं स्मार्ट थीं और बाद में किसी ने सोचा था कि ऑटो- (संयुक्त राष्ट्र) बॉक्सिंग और भी स्मार्ट था ... और उन लोगों के नाम का उपयोग कर एपीआई का उपयोग कर रहा था। जब मौजूदा परिणाम बेहतर है । बहुत सारे उद्देश्यों के लिए नए Arraylist <Integer> की तुलना में बेहतर समाधान हैं । उदाहरण के लिए ट्रोव चीजों को एक TIntArrayList प्रदान करता है । जावा (SCJP में 2001 के बाद से) मैं जितना अधिक कार्यक्रम करता हूं, मैं रैपर कक्षाओं का कम उपयोग करता हूं और जितना अधिक मैं अच्छी तरह से डिजाइन किए गए एपीआई (ट्रोव, Google, आदि का उपयोग करता हूं) का ध्यान रखते हैं।
SyntaxT3rr0r

जवाबों:


230

जावा हमेशा उस विधि को कहता है जो आपके तर्क को सबसे अच्छी तरह से सूट करती है। ऑटो बॉक्सिंग और निहित अपकास्टिंग केवल तभी किया जाता है जब कोई विधि न हो जिसे कास्टिंग / ऑटो बॉक्सिंग के बिना कहा जा सकता है।

सूची इंटरफ़ेस दो हटाने के तरीके निर्दिष्ट करता है (कृपया तर्कों के नामकरण पर ध्यान दें):

  • remove(Object o)
  • remove(int index)

इसका मतलब है कि list.remove(1)वस्तु को स्थिति 1 पर remove(new Integer(1))हटा दिया जाता है और इस सूची से निर्दिष्ट तत्व की पहली घटना को हटा देता है।


110
नाइटिंग चुनना: Integer.valueOf(1)से बेहतर अभ्यास है new Integer(1)। स्थैतिक विधि कैशिंग और ऐसे कर सकती है, जिससे आपको बेहतर प्रदर्शन मिलेगा।
डिक्रिप्ट

पीटर लॉरी का प्रस्ताव बेहतर है और अनावश्यक वस्तु कृतियों से बचा जाता है।
assylias

@assylias: पीटर लॉरी का प्रस्ताव ठीक उसी तरह का काम करता है जैसा कि डिक्रिप्ट का प्रस्ताव, केवल कम पारदर्शी तरीके से।
मार्क पीटर्स

@MarkPeters मेरी टिप्पणी के बारे में था new Integer(1), लेकिन मैं सहमत हूं कि Integer.valueOf(1)या (Integer) 1समकक्ष हैं।
अस्वच्छ

68

आप कास्टिंग का उपयोग कर सकते हैं

list.remove((int) n);

तथा

list.remove((Integer) n);

इससे कोई फर्क नहीं पड़ता कि n एक इंट या इंटेगर है या नहीं, विधि हमेशा आपके द्वारा अपेक्षित फोन करेगी।

उपयोग करना (Integer) nया पहले की Integer.valueOf(n)तुलना new Integer(n)में अधिक कुशल है क्योंकि पहले दो इंटेगर कैश का उपयोग कर सकते हैं, जबकि बाद में हमेशा एक वस्तु का निर्माण होगा।


2
यह अच्छा होगा यदि आप समझा सकते हैं कि ऐसा क्यों है :) [ऑटोबॉक्सिंग की स्थिति ...]
युवल एडम

कास्टिंग का उपयोग करके, आप यह सुनिश्चित करते हैं कि कंपाइलर आपके द्वारा अपेक्षित प्रकार देखता है। पहले मामले में '(int) एन' ही प्रकार के हो सकते हैं पूर्णांक दूसरे मामले '(पूर्णांक) एन' में ही प्रकार के हो सकते हैं पूर्णांक । आवश्यकतानुसार 'n' को परिवर्तित / बॉक्सिंग / अनबॉक्स किया जाएगा या नहीं होने पर आपको संकलक त्रुटियां मिलेंगी।
पीटर लॉरी

10

मैं 'उचित' तरीके के बारे में नहीं जानता, लेकिन आपने जिस तरह से काम किया है वह ठीक है:

list.remove(int_parameter);

तत्व को दिए गए स्थान पर हटा देता है और

list.remove(Integer_parameter);

दी गई वस्तु को सूची से हटा देता है।

क्योंकि विधि को खोजने के लिए पहला प्रयास पर वी एम के साथ घोषित यह वास्तव में एक ही पैरामीटर प्रकार और उसके बाद ही autoboxing की कोशिश करता है।


7

list.remove(4)का सटीक मिलान है list.remove(int index), इसलिए इसे कहा जाएगा आप कॉल करना चाहते हैं list.remove(Object): निम्नलिखित करना list.remove((Integer)4)


धन्यवाद पेटर, (Integer)जैसा कि आपने ऊपर लिखा एक साधारण कलाकार मेरे लिए सबसे आसान तरीका है।
10

अपने अंतिम दृष्टिकोण का उपयोग करते समय, यह एक बूलियन को वापस करने के लिए लगता है। जब कई हटाने की कोशिश की जाती है तो मुझे वह त्रुटि मिलती है जिसे मैं बूलियन पर हटाने को नहीं कह सकता।
ब्रैम वेनरो

4

जब आप list.remove (1) निष्पादित करते हैं तो क्या होता है, इस पर कोई शिक्षित अनुमान है? List.remove (नया इंटेगर (1)) के बारे में क्या?

अनुमान लगाने की कोई जरूरत नहीं है। पहले मामले को List.remove(int)बुलाया जाएगा, और स्थिति में तत्व को 1हटा दिया जाएगा। दूसरे मामले का परिणाम List.remove(Integer)कहा जाएगा, और वह तत्व जिसका मूल्य बराबर Integer(1)है हटा दिया जाएगा। दोनों मामलों में, जावा कंपाइलर निकटतम मिलान अधिभार का चयन करता है।

हां, यहां भ्रम (और कीड़े) होने की संभावना है, लेकिन यह काफी असामान्य उपयोग-मामला है।

जब दो List.remove जावा 1.2 में तरीकों को परिभाषित किया गया था, तो अधिभार अस्पष्ट नहीं थे। केवल जावा 1.5 में जेनरिक और ऑटोबॉक्सिंग की शुरुआत के साथ समस्या उत्पन्न हुई। हिंद-दृष्टि में, यह बेहतर होता अगर हटाने के तरीकों में से एक को एक अलग नाम दिया गया होता। लेकिन अब बहुत देर हो चुकी है।


2

ध्यान दें कि भले ही VM ने सही काम नहीं किया है, जो वह करता है, आप अभी भी remove(java.lang.Object)मध्यस्थ वस्तुओं पर संचालित होने वाले तथ्य का उपयोग करके उचित व्यवहार सुनिश्चित कर सकते हैं:

myList.remove(new Object() {
  @Override
  public boolean equals(Object other) {
    int k = ((Integer) other).intValue();
    return k == 1;
  }
}

यह "समाधान" equalsविधि के अनुबंध को तोड़ता है , विशेष रूप से (जावदोक से) "यह सममित है: किसी भी गैर-शून्य संदर्भ मानों के लिए x और y, x.equals (y) सही होना चाहिए अगर और केवल y.equals ( x) सही लौटाता है। ” जैसे कि यह सभी कार्यान्वयन पर काम करने की गारंटी नहीं है List, क्योंकि सूची के किसी भी कार्यान्वयन को x और y को एक साथ स्वैप करने की अनुमति है x.equals(y), क्योंकि Javadoc का Object.equalsकहना है कि यह मान्य होना चाहिए।
इरविन बोलाविद्ट

1

जैसा कि मैंने पहले उत्तर में पहली टिप्पणी में #decitrig द्वारा सुझाए गए अनुसार पसंद किया था।

list.remove(Integer.valueOf(intereger_parameter));

इससे मुझे मदद मिली। आपकी टिप्पणी के लिए फिर से #decitrig धन्यवाद। यह किसी एक के लिए मदद कर सकता है।


0

वैसे यहाँ चाल है।

आइए यहां दो उदाहरण लेते हैं:

public class ArrayListExample {

public static void main(String[] args) {
    Collection<Integer> collection = new ArrayList<>();
    List<Integer> arrayList = new ArrayList<>();

    collection.add(1);
    collection.add(2);
    collection.add(3);
    collection.add(null);
    collection.add(4);
    collection.add(null);
    System.out.println("Collection" + collection);

    arrayList.add(1);
    arrayList.add(2);
    arrayList.add(3);
    arrayList.add(null);
    arrayList.add(4);
    arrayList.add(null);
    System.out.println("ArrayList" + arrayList);

    collection.remove(3);
    arrayList.remove(3);
    System.out.println("");
    System.out.println("After Removal of '3' :");
    System.out.println("Collection" + collection);
    System.out.println("ArrayList" + arrayList);

    collection.remove(null);
    arrayList.remove(null);
    System.out.println("");
    System.out.println("After Removal of 'null': ");
    System.out.println("Collection" + collection);
    System.out.println("ArrayList" + arrayList);

  }

}

अब आउटपुट पर एक नजर डालते हैं:

Collection[1, 2, 3, null, 4, null]
ArrayList[1, 2, 3, null, 4, null]

After Removal of '3' :
Collection[1, 2, null, 4, null]
ArrayList[1, 2, 3, 4, null]

After Removal of 'null': 
Collection[1, 2, 4, null]
ArrayList[1, 2, 3, 4]

अब आउटपुट का विश्लेषण करते हैं:

  1. जब 3 संग्रह से हटा दिया जाता है तो यह संग्रह की remove()विधि को कॉल करता है जो Object oपैरामीटर के रूप में लेता है । इसलिए यह वस्तु को हटा देता है 3। लेकिन arrayList ऑब्जेक्ट में इसे इंडेक्स 3 द्वारा ओवरराइड किया जाता है और इसलिए 4 वें तत्व को हटा दिया जाता है।

  2. ऑब्जेक्ट के एक ही तर्क द्वारा नल को दूसरे आउटपुट में दोनों मामलों में हटा दिया जाता है।

इसलिए 3जो संख्या एक वस्तु है उसे निकालने के लिए हमें स्पष्ट रूप से 3 को पास करने की आवश्यकता होगी object

और रैपर क्लास का उपयोग करके कास्टिंग या रैपिंग द्वारा किया जा सकता है Integer

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

Integer removeIndex = Integer.valueOf("3");
collection.remove(removeIndex);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.