दिलचस्प पोस्ट
ऑपरेटर से अधिक या उससे कम का उपयोग करते हुए दो सूचियों की तुलना करना सी ++ सीमा पुनरावर्ती गहराई है? चयन के जरिए ओपन यूआरएल यूआरएल – jQuery XML दस्तावेज़ को सी # में पार्स करें सी # हैश_हैमक के बराबर PHP में एक एमवीवीएम मित्रवत संवाद रणनीति बनाना एंड्रॉइड में "वर्चुअल कीबोर्ड शो / छिपाना" कैसे कैप्चर करें? वेब अनुप्रयोगों में एनिमेटेड कर्सर समर्थन? विंडोज लाइब्रेरी (* .lib) की सामग्री को कैसे देखें जावास्क्रिप्ट फ़ंक्शन प्रमुख बैंग! वाक्य – विन्यास GitHub को धकेलने में त्रुटि – रिपॉजिटरी डेटाबेस को ऑब्जेक्ट जोड़ने के लिए अपर्याप्त अनुमति Printf में "%। * S" क्या होता है? लीप वर्ष की गणना के लिए जावा कोड क्या समान SQL कथन में एकाधिक तालिकाओं से हटाना संभव है? उपयोगकर्ता के समय क्षेत्र को अनदेखा कैसे करें और बल तिथि () विशिष्ट समय क्षेत्र का उपयोग करें

कैसे जावा एटिल से बचें। कॉन्ट्रैक्टमोडिफिकेशन अपेशन जब किसी अररियलिस्ट से तत्वों को निकालते और निकालते हैं

मेरे पास एक सरणी सूची है जो मैं फिर से करना चाहता हूं। इस पर फिर से चलने पर मुझे एक ही समय में तत्वों को निकालना होगा। जाहिर है यह एक java.util.ConcurrentModificationException फेंकता है।

इस समस्या को संभालने के लिए सबसे अच्छा अभ्यास क्या है? क्या मुझे सूची पहले क्लोन करना चाहिए?

मैं तत्वों को लूप में नहीं हटाता, लेकिन कोड का दूसरा भाग।

मेरा कोड इस तरह दिखता है:

  public class Test() { private ArrayList<A> abc = new ArrayList<A>(); public void doStuff() { for (A a : abc) a.doSomething(); } public void removeA(A a) { abc.remove(a); } } 

a.do कुछ कह सकते हैं टेस्ट .removeA ();

Solutions Collecting From Web of "कैसे जावा एटिल से बचें। कॉन्ट्रैक्टमोडिफिकेशन अपेशन जब किसी अररियलिस्ट से तत्वों को निकालते और निकालते हैं"

दो विकल्प:

  • उन मानों की एक सूची बनाएँ, जिन्हें आप हटाना चाहते हैं, उस सूची में लूप में जोड़कर , फिर originalList.removeAll(valuesToRemove) को अंत में कॉल करें
  • इटरेटर पर खुद को remove() विधि का उपयोग करें ध्यान दें कि इसका मतलब है कि आप लूप के लिए बढ़ाया उपयोग नहीं कर सकते।

दूसरे विकल्प का एक उदाहरण के रूप में, किसी सूची से 5 से अधिक लंबाई वाली किसी भी स्ट्रिंग को निकालना:

 List<String> list = new ArrayList<String>(); ... for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) { String value = iterator.next(); if (value.length() > 5) { iterator.remove(); } } 

ArrayList के जावा डॉक्स से

इस वर्ग के इटरेटर और सूची से लौटे Iterator यंत्रों को विफल-तेज़ी से किया जाता है: यदि सूची स्थैतिक रूप से इरेरेक्टर के बाद किसी भी समय संरचनात्मक रूप से संशोधित की जाती है, तो इटरेटर के स्वयं के हटाने या विधियों को छोड़कर किसी भी तरह से, इटरेटर एक समवर्तीमोडिफिकेशन अपवाद फेंकता है।

एक विकल्प को removeA विधि को इस पर संशोधित करना है –

 public void removeA(A a,Iterator<A> iterator) { iterator.remove(a); } 

लेकिन इसका मतलब यह होगा कि आपका doSomething() को iterator को remove विधि से पास करने में सक्षम होना चाहिए। बहुत अच्छा विचार नहीं

क्या आप इसे दो चरण के दृष्टिकोण में कर सकते हैं: जब आप सूची में दोबारा शुरू करते हैं, तो पहले लूप में चयनित तत्वों को हटाने के बजाय, उन्हें हटाए जाने के रूप में चिह्नित करें इसके लिए, आप इन तत्वों (उथले प्रतिलिपि) को दूसरी List में कॉपी कर सकते हैं।

फिर, एक बार आपका पुनरावृत्त किया जाता है, बस एक removeAll । पहली सूची से सभी दूसरी सूची में सभी तत्व।

आपको वास्तव में पारंपरिक तरीके से सिर्फ सरणी को वापस करना चाहिए

हर बार जब आप सूची से एक तत्व निकाल देते हैं, तो तत्व आगे बढ़ेगा। जब तक आप इटरेटिंग के अलावा अन्य तत्व नहीं बदलते हैं, तब तक निम्न कोड को काम करना चाहिए।

 public class Test(){ private ArrayList<A> abc = new ArrayList<A>(); public void doStuff(){ for(int i = (abc.size() - 1); i >= 0; i--) abc.get(i).doSomething(); } public void removeA(A a){ abc.remove(a); } } 

यहाँ एक उदाहरण है जहां मैं हटाने के लिए वस्तुओं को जोड़ने के लिए एक अलग सूची का उपयोग करता हूं, फिर बाद में मैं स्ट्रीम का उपयोग करता हूं। फोरेक मूल सूची से तत्वों को निकालने के लिए:

 private ObservableList<CustomerTableEntry> customersTableViewItems = FXCollections.observableArrayList(); ... private void removeOutdatedRowsElementsFromCustomerView() { ObjectProperty<TimeStamp> currentTimestamp = new SimpleObjectProperty<>(TimeStamp.getCurrentTime()); long diff; long diffSeconds; List<Object> objectsToRemove = new ArrayList<>(); for(CustomerTableEntry item: customersTableViewItems) { diff = currentTimestamp.getValue().getTime() - item.timestamp.getValue().getTime(); diffSeconds = diff / 1000 % 60; if(diffSeconds > 10) { // Element has been idle for too long, meaning no communication, hence remove it System.out.printf("- Idle element [%s] - will be removed\n", item.getUserName()); objectsToRemove.add(item); } } objectsToRemove.stream().forEach(o -> customersTableViewItems.remove(o)); } 

आप उन्नत "लूप के लिए" सूची से मूल्य को निकालने का प्रयास कर रहे हैं, जो संभव नहीं है, भले ही आप कोई भी चाल (जो आपने अपने कोड में किया था) लागू करते हैं। बेहतर तरीका है कोड इटरेटर स्तर के लिए जैसा कि अन्य यहां सलाह दी गई है।

मुझे आश्चर्य है कि लोगों ने लूप दृष्टिकोण के लिए परंपरागत सुझाव नहीं दिया है।

 for( int i = 0; i < lStringList.size(); i++ ) { String lValue = lStringList.get( i ); if(lValue.equals("_Not_Required")) { lStringList.remove(lValue); i--; } } 

यह भी काम करता है

सामान्य तरीके से पाश करें, java.util.ConcurrentModificationException से संबंधित त्रुटि है।

इसलिए कोशिश करें:

 for(int i = 0; i < list.size(); i++){ lista.get(i).action(); } 

इस तरह से कुछ आसान करना:

 for (Object object: (ArrayList<String>) list.clone()) { list.remove(object); } 

"क्या मुझे सूची पहले क्लोन करना चाहिए?"

यह सबसे आसान समाधान होगा, क्लोन से हटा दें, और हटाने के बाद क्लोन को वापस कॉपी करें।

मेरे रम्मीकिब गेम से एक उदाहरण:

 SuppressWarnings("unchecked") public void removeStones() { ArrayList<Stone> clone = (ArrayList<Stone>) stones.clone(); // remove the stones moved to the table for (Stone stone : stones) { if (stone.isOnTable()) { clone.remove(stone); } } stones = (ArrayList<Stone>) clone.clone(); sortStones(); } 

जावा 8 में आप संग्रह इंटरफेस का उपयोग कर सकते हैं और इसे हटाने का तरीका कॉल करके कर सकते हैं:

 yourList.removeIf((A a) -> a.value == 2); 

अधिक जानकारी यहां पाई जा सकती है