दिलचस्प पोस्ट
Xcode डुप्लिकेट लाइन Django / Comet (पुश): सभी बुराइयों में से कम? मैं दशमलव के रूप में एक इंट क्यों नहीं खुल सकता? सी # डेस्कटॉप अनुप्रयोग में एम्बेड करने के लिए सबसे अच्छी स्क्रिप्टिंग भाषा क्या है? कंसोल परिणामों पर जावास्क्रिप्ट चर घोषणा क्यों "अपरिभाषित" मुद्रित किया जा रहा है? अजगर में नकारात्मक संख्या मॉड्यूलो HTTP और REST के बीच अंतर क्या है? मैं WebClient के साथ किसी साइट में कैसे प्रवेश करूं? क्या हैं और वे उपयोगी क्यों हैं? फ़ाइल डाउनलोड के लिए HTTP शीर्षलेख एएसपी.नेट एमवीसी में संभावित बग में बदला जा सकता है प्राधिकरण सर्वर समापन बिंदु कॉन्फ़िगर करें क्या सिस्टम के लिए एक टास्क आधारित प्रतिस्थापन है। थ्रेडिंग। टिमर? उद्देश्य-सी – एएपीएशन के बाद परिवर्तन लागू करने वाले सीएबीएसिक एनीमेशन? एफपीडीएफ यूटीएफ -8 एन्कोडिंग (एचओ-टू)

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

मेरे पास एक सरणी सूची है जो मैं फिर से करना चाहता हूं। इस पर फिर से चलने पर मुझे एक ही समय में तत्वों को निकालना होगा। जाहिर है यह एक 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 ();

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

दो विकल्प:

  • उन मानों की एक सूची बनाएँ, जिन्हें आप हटाना चाहते हैं, उस सूची में लूप में जोड़कर , फिर 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); 

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