2009-03-09 11 views
17

यह प्रश्न this question में वर्णित समस्या (और हल) की एक और विशेष मामला है।जावा: इसे ऊपर/जोड़ते समय सूची से तत्वों को कैसे हटाएं

मेरे पास दो विधियां हैं, रोकें और हटाएं (सर्वर ऑब्जेक्ट सर्वर) और एक करीबी() विधि। बाद में सभी सर्वर बंद करना चाहिए और उन्हें सर्वर सूची से हटा देना चाहिए। इस रूप में,

public void closeCurrentlyOpen() { 
    for(ServerObject server : this.servers) { 
     stopAndRemove(server) 
    } 
} 

यह काम नहीं करेगा: सूची

List<ServerObject> server. 

के रूप में परिभाषित किया गया है मैं closeCurrentlyOpen में stopAndRemove से लगभग एक ही कोड है नहीं करना चाहते, तो मैं कुछ ऐसा करना चाहते हैं एक ConcurrentModificationException का कारण बन जाएगा। मैं इस सूची

List<ServerObject> copyList = new ArrayList<ServerObject>(this.servers); 

की एक प्रतिलिपि बनाने और उपयोग करें कि foreach पाश के लिए सूची के रूप में करने की कोशिश की। लेकिन फिर यह संभव हो सकता है कि एक अन्य थ्रेड सर्वर सूची में सर्वर को जोड़ता है, जबकि मैं कॉपीलिस्ट पर पुनरावृत्ति कर रहा हूं लेकिन बंद करें वर्तमान में ओपेन को एक एम्प्पी सूची में परिणाम माना जाता है। addServerToList विधि के रूप में सर्वर-सूची में समन्वयित किया जाता कर इस

public void closeCurrentlyOpen() { 
    synchronized(this.servers) { 
    for(ServerObject server : this.servers) { 
     stopAndRemove(server) 
    } 
    } 
} 

संशोधनों के साथ समस्या का समाधान होगा। लेकिन फिर मैं स्टॉप एंड्रॉम विधि में कोड को सिंक्रनाइज़ नहीं कर सकता जो आवश्यक है अगर इसे सीधे कहा जाता है।

मुझे लगता है कि इन तीन तरीकों के डिजाइन को शायद एक वर्कओवर की आवश्यकता है। कोई विचार?

उत्तर

17

स्टॉप एंड रिमूव() से एक विधि स्टॉप() को विभाजित करें। फिर लूप को एक स्पष्ट इटरेटर के साथ लिखें, स्टॉप करें और फिर iterator.remove()।

"और" विधि नाम में कोड गंध है।

+0

मैं बहुत किया है ... रोकने के पाश से सभी तत्वों को रोकने,() सभी को दूर करने के तो list.clean। हां, "और" यहां कोड गंध है। मैंने इसे इस नाम में उदाहरण दिया है इसलिए मुझे यह वर्णन करने की आवश्यकता नहीं है कि मैं क्या करता हूं। – Arvodan

4

जब मैंने इसे पहले किया है, तो मैंने हमेशा "पुराने स्कूल" लिंक्डलिस्ट संग्रह, एक इटरेटर और Iterator.remove() विधि का उपयोग वर्तमान आइटम को हटाने के लिए किया था।

2

स्टॉप से ​​सभी सर्वर ऑब्जेक्ट स्टॉपिंग कोड को रिफैक्टर करें और एक निजी स्टॉप सर्वर विधि में हटाएं, और फिर अलग-अलग हटाने को रोकें और हटाएं और बंद करें वर्तमान में खोलें। फिर आप उन्हें हटाने के लिए ListIterator का उपयोग कर सकते हैं (या बस उन्हें लूप के लिए सभी को रोकें और अंत में सूची साफ़ करें)।

+0

इस तरह से मैं इसे अभी कर सकता हूं। मुझे लगता है कि स्टारब्लू ने भी सुझाव दिया है। – Arvodan

0

आपको एक इटरेटर प्राप्त करना चाहिए और इसका उपयोग करना चाहिए। आपको अपवाद मिल रहा है क्योंकि जावा में इटरेटर fail-fast हैं।

+0

मैं नीचे मतदाता नहीं कर रहा हूँ, लेकिन: यह इटरेटर कि असफल फास्ट रहे हैं, लेकिन JDK में प्रदान की गई सूची के कार्यान्वयन नहीं है। – Nicolas

+0

शायद मुझे यह कहना चाहिए था कि जावा संग्रह का उपयोग तेजी से इटरेटर्स विफल हो गया है। – amit

13

शायद यह करने का गलत तरीका है, लेकिन मैं हमेशा एक निष्कासन संग्रह बना देता हूं, जिसमें उन वस्तुओं को इंडेक्स या संदर्भ शामिल होते हैं जिन्हें निकालने की आवश्यकता होती है। मैं फिर उस संग्रह पर पुन: प्रयास करता हूं और मूल संग्रह से उन अनुक्रमणिका/वस्तुओं को हटा देता हूं। शायद सबसे कुशल नहीं है लेकिन यह काम पूरा हो गया।

for(Collection things : thing) 
    things.remove(thing) 

के बजाय

मैं

Collection toRemove = new LinkedList(); 
for(things : thing) 
    toRemove.add(thing); 

for(toRemove : thing) 
    things.remove(thing) 
+0

नहीं, यह करने का सही तरीका है। या हटाए गए आइटमों के बिना एक नया संग्रह बनाएं और इसके साथ मूल संग्रह को प्रतिस्थापित करें। एक संग्रह है, जबकि आप के माध्यम से पुनरावृत्ति कर रहे हैं से आइटम निकाले जा रहे है कि imperetive कोड एक बुरा नाम :) देता है बकवास की तरह है – U62

+2

जरूरी * क्षमा करें, मैं इसे मदद नहीं कर सकता :( –

+0

समस्या मैं यहाँ देखें: इस समाधान चाहते हैं सूची में डेटा जोड़ने से किसी भी धागा बंद करो। इस से ऊपर अन्य समाधान synchronzied-ब्लॉक के माध्यम से किया जाता है। – Arvodan

1

का उपयोग सवाल है, नहीं दिए गए उदाहरण के विशिष्ट विवरण के शीर्षक के उत्तर देना। वास्तव में, यह समाधान दिए गए परिस्थिति में भी उचित नहीं है (रीफैक्टरिंग उचित है, जैसा कि दूसरों द्वारा सुझाया गया है)।

हालांकि, ऐसा लगता है कि कई जावा प्रोग्रामर CopyOnWriteArrayList (1.5 से जेडीके का हिस्सा) से अवगत नहीं हैं और एक ही समस्या (पुनरावृत्ति से पहले प्रतिलिपि सूची) के लिए अपने स्वयं के समाधान रोल करने की कोशिश कर रहे हैं।

1

... फ़ाइलों को एक निर्देशिका सूची से XML नहीं हैं को हटाने ...

List<File> files = Arrays.asList(dir.listFiles()); 

Iterator<File> i = files.iterator(); 

while (i.hasNext()) { 
    File file = i.next(); 
    if (!file.getName().endsWith(".xml")) { 
     i.remove(); 
    } 
} 
+0

बस ध्यान दें कि यह करने के लिए यह * आदर्श * तरीका नहीं है। – Spider

+0

यदि कोई जानता है कि इस पर लॉक कैसे जोड़ना है, तो मुझे यह देखना अच्छा लगेगा कि कैसे। यह तब यह एक ठोस उदाहरण मेथिंक बना देगा। – Spider

+0

JDK7 में, मुझे मिल गया * धागा "मुख्य" java.lang.UnsupportedOperationException में अपवाद * क्योंकि * Arrays.asList * वापसी तय हो गई सूची का आकार। – vanduc1102

1

firebird84 की ही तरह। लेकिन आप removeAll (संग्रह सी) एपीआई

for(String exitingPermission : existingPermissions){     
    //remove all permissions for the screen and add the new ones 
    if(exitingPermission.split("_")[0].equals(screen)){ 
     removePermissions.add(exitingPermission); 
    } 
} 
existingPermissions.removeAll(removePermissions); 

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

  • कोई संबंधित समस्या नहीं^_^