2015-03-01 12 views
6

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

इस उद्देश्य के लिए आप क्या उपयोग कर रहे हैं?

संपादित करें:

मैं grepcode पर पाया removeAll का कोड कॉल batchRemove (ग, गलत):

निजी बूलियन अधिक ... batchRemove (संग्रह ग, बूलियन पूरक) {

700   final Object[] elementData = this.elementData; 
701   int r = 0, w = 0; 
702   boolean modified = false; 
703   try { 
704    for (; r < size; r++) 
705     if (c.contains(elementData[r]) == complement) 
706      elementData[w++] = elementData[r]; 
707   } finally { 
708    // Preserve behavioral compatibility with AbstractCollection, 
709    // even if c.contains() throws. 
710    if (r != size) { 
711     System.arraycopy(elementData, r, 
712         elementData, w, 
713         size - r); 
714     w += size - r; 
715    } 
716    if (w != size) { 
717     // clear to let GC do its work 
718     for (int i = w; i < size; i++) 
719      elementData[i] = null; 
720     modCount += size - w; 
721     size = w; 
722     modified = true; 
723    } 
724   } 
725   return modified; 
726  } 

:

मैं वास्तव में यह समझ में न ..

अपने परीक्षण कोड यह था

public class RemoveVsRemovall { 

    public static void main(String[] args){ 
     ArrayList<String> source = new ArrayList<>(); 
     ArrayList<String> toRemove = new ArrayList<>(); 
     for(int i = 0; i < 30000; i++){ 
      String s = String.valueOf(System.nanoTime()); 
      source.add(s); 
      if(i % 2 == 0) toRemove.add(s); 
     } 
     long startTime = System.nanoTime(); 
     removeList1(source, toRemove); 
     long endTime = System.nanoTime(); 
     System.out.println("diff: " + (endTime - startTime) * 1e-9); 
    } 

    static void removeList1(ArrayList<String> source, ArrayList<String> toRemove){ 
     source.removeAll(toRemove); 
    } 

    static void removeList2(ArrayList<String> source, ArrayList<String> toRemove){ 
     for(String s : toRemove){ 
      source.remove(s); 
     } 
    } 
} 

इसे विभिन्न सूची आकारों के साथ कुछ बार बुला रहा है और दो तरीकों से between स्विचिंग।

+4

मुझे उम्मीद है कि आपके परीक्षण में कोई दोष था। हमें अपना टेस्ट कोड दिखाएं। (मुझे यह विश्वास करना मुश्किल लगता है कि * वास्तव में * प्रदर्शन में एक महत्वपूर्ण अंतर है। और जावा में सटीक परिणाम देने वाले बेंचमार्क लिखना कठिन है।) –

+0

आप सभी विधियों को हटाने और निकालने के लिए कोड क्यों नहीं देखते हैं? फिर भी, यह सवाल एक डाउनवोट के लायक नहीं है। मुझसे +1 इस पर 200 + अपवॉट्स के साथ SO पर खराब प्रश्न हैं .. – CKing

+0

@bot और क्या मैं पूछ सकता हूं कि प्रगति कहां है? – Gabe

उत्तर

4

ऐसे कई कारण हैं जो उस प्रश्न का सामान्य उत्तर देना मुश्किल है।

सबसे पहले, आपको यह समझना होगा कि ये प्रदर्शन विशेषताएं कार्यान्वयन-निर्भर हैं। यह काफी संभव है कि कार्यान्वयन जेडीके के मंच और संस्करण के आधार पर भिन्न होता है।

कहा करने के बाद वहाँ ज्यादातर हैं कि, removeAll लागू करने के लिए 2 रणनीति:

  1. अपने ArrayList के प्रत्येक तत्व के लिए, यदि यह अन्य Collection में है की जांच; यदि हां, तो इसे हटा दें।
  2. Collection के प्रत्येक तत्व के लिए, जांचें कि यह ArrayList में है या नहीं; यदि हां, तो इसे हटा दें।

यदि Collection प्रदर्शन लगातार समय में होता है, तो रणनीति 1 (asymptotically) जीतता है। दूसरी तरफ, यदि contains पूरे कनेक्शन स्कैन करके किया जाता है और Collection बहुत धीरे-धीरे पुनरावृत्त होता है, तो रणनीति 2 में आमतौर पर किनारे होती है, क्योंकि यह केवल Collection पर फिर से होती है; लेकिन उस स्थिति में भी, यदि Collection बहुत बड़ा है और ArrayList के अधिकांश तत्व Collection के पहले तत्वों में से हैं, तो रणनीति 1 फिर से जीत जाती है ... इसका कोई अंत नहीं है।

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

2

एक और बात पर विचार करना:

जावा के कोड उम्र के लिए battletested गया है, और इतनी के रूप में अलग अलग और विशेष मामलों (टिप्पणी Preserve behavioral compatibility with AbstractCollection देखें) का एक बहुत करने के लिए अनुकूल करने के लिए लिखा है।

तो, वास्तव में यह संभव है कि आप विधियों के अपने कार्यान्वयन को लिख सकें, जो तेजी से चलेंगे। लेकिन दूसरी तरफ, क्या आप वाकई जावा के जन्म के बाद से जावा देवों के सभी विशेष मामलों का सामना कर सकते हैं?

यह भी ध्यान में रखें कि कुछ जावा फ़ंक्शंस चीजों को गति देने के लिए कुछ सी कार्यान्वयन का उपयोग कर रहे हैं। जाहिर है यह मामला यहां नहीं है, लेकिन यह हो सकता है।

+0

तो आप removeAll का उपयोग करने की सिफारिश कर रहे हैं? –

+0

जब तक आप वास्तव में इष्टतम प्रदर्शन की परवाह नहीं करते हैं, और आप जानते हैं कि आपको केवल विशिष्ट डेटासेट से निपटना होगा, जो आपके बेंचमार्क कोड के समान व्यवहार करेगा (नरक मुझे यह भी सुनिश्चित नहीं है कि यह आसानी से जांचना संभव हो), हाँ। –

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