2011-06-08 18 views
5

मुझे एक ArrayList फ़िल्टर करने और पाया तत्वों को हटाने की जरूरत है। जावा के लिए अपेक्षाकृत नया होने के नाते, मैं सोच रहा हूं कि यह हासिल करने के लिए सबसे प्रभावशाली तरीका क्या है (महत्वपूर्ण है क्योंकि यह मोबाइल उपकरणों पर चलता है)। वर्तमान में मैं यह करता हूं:जावा: कुशल ArrayList फ़िल्टरिंग?

// We display only top-level dealers (parentId=-10) 
ArrayList<DealerProductCount> subDealers = new ArrayList<DealerProductCount>(); 
for (DealerProductCount dealer : wsResponse.Dealers) { 
    if (dealer.ParentId != -10) subDealers.add(dealer); 
} 
wsResponse.Dealers.removeAll(subDealers); 

क्या यह अस्थायी वस्तुओं के बिना किया जा सकता है? शायद सूची के तत्वों को सीधे छेड़छाड़ करके (हटाया जा रहा है)?

+1

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

उत्तर

16

कुशलतापूर्वक एक ArrayList से तत्वों की एक संख्या को हटाने के कुछ विचार की आवश्यकता है।

Iterator<DealerProductCount> it = wsResponse.Dealers.iterator(); 
while (it.hasNext()) { 
    if (it.next().ParentId != -10) { 
     it.remove(); 
    } 
} 

समस्या यह है कि हर बार जब आप एक तत्व आप (औसतन) कॉपी शेष तत्वों में से आधे को दूर है: अनुभवहीन दृष्टिकोण कुछ इस तरह है। ऐसा इसलिए है क्योंकि ArrayList से तत्व को हटाने से तत्व के बाद सभी तत्वों को प्रतिलिपि बनाना आवश्यक है, बाईं ओर एक स्थिति हटा दी गई है।

तत्वों की सूची को शामिल करने वाला आपका मूल समाधान अनिवार्य रूप से वही काम करता है। दुर्भाग्यवश, ArrayList के गुण उपरोक्त से बेहतर करने के लिए removeAll की अनुमति नहीं देते हैं।

आप तत्वों की एक संख्या को दूर करने की उम्मीद है, तो निम्न और अधिक कुशल है:

ArrayList<DealerProductCount> retain = 
     new ArrayList<DealerProductCount>(wsResponse.Dealers.size()); 
for (DealerProductCount dealer : wsResponse.Dealers) { 
    if (dealer.ParentId == -10) { 
     retain.add(dealer); 
    } 
} 
// either assign 'retain' to 'wsResponse.Dealers' or ... 
wsResponse.Dealers.clear(); 
wsResponse.Dealers.addAll(retain); 

हम (लगभग) कॉपी कर रहे हैं पूरी सूची में दो बार, तो यह भी (औसतन) का विश्लेषण करना चाहिए अगर आप को दूर 4 तत्वों के रूप में कम से कम।


ऐसा नहीं है कि कार्यात्मक प्रोग्रामिंग भाषाओं/पुस्तकालयों नोट करने के लिए ठेठ समर्थन एक फिल्टर विधि दिलचस्प है, और उस सूची के माध्यम से एक पास में यह काम पूरा कर सकते हैं; यानी बहुत अधिक कुशलता से। मुझे लगता है कि अगर जावा लैम्बडा का समर्थन करता है तो हम महत्वपूर्ण सुधार की उम्मीद कर सकते हैं, और संग्रह API को उनका उपयोग करने के लिए बढ़ाया जाता है।

+0

धन्यवाद स्टीफन, आपके शानदार गहराई से स्पष्टीकरण के लिए! तो ले-होम संदेश यह है कि मौजूदा एरे तत्वों को निकालने के बजाय एक नया ऐरेलिस्ट भरना आम तौर पर बेहतर होता है। जानकार अच्छा लगा! – Bachi

7

यदि आप एक पुनरावर्तक का उपयोग करते हैं तो आप इसे सक्रिय करते समय सुरक्षित तत्वों को हटा सकते हैं।

+1

(यदि इटरेटर हटाने के लिए एक कार्यान्वयन प्रदान करता है - यह एक 'असमर्थितऑपरेशन अपवाद' फेंक सकता है - तो यह केवल तभी काम करता है जब आप * अपने इटरेटर को अच्छी तरह से जानते हों) –

4

एक तरह से प्रत्येक के लिए के बजाय इटरेटर का प्रयोग करेंगे:

Iterator<DealerProductCount> iter = wsResponse.Dealers.iterator() 
while(iter.hasNext()) { 
    if (iter.next().ParentId != -10) iter.remove(); 
}