यदि आप अपने सेट में तत्वों पर जाने के लिए एक इटेरेटर ऑब्जेक्ट का उपयोग करते हैं, तो आप क्या कर सकते हैं। आप उन्हें चलते-फिरते ठीक कर सकते हैं। हालाँकि उन्हें लूप में रखते समय (या तो "मानक", प्रत्येक प्रकार के लिए) आपको परेशानी में डाल देगा:
Set<Integer> set = new TreeSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
Iterator<Integer> iterator = set.iterator();
while(iterator.hasNext()) {
Integer setElement = iterator.next();
if(setElement==2) {
iterator.remove();
}
}
for(Integer setElement:set) {
if(setElement==2) {
set.remove(setElement);
}
}
@ मृग्लोम की टिप्पणी के अनुसार, यहां अधिक विवरण दिए गए हैं कि "खराब" तरीका ऊपर वर्णित क्यों है, अच्छी तरह से ... बुरा:
जावा उच्च स्तर पर इसे कैसे लागू करता है, इस बारे में बहुत अधिक जानकारी प्राप्त किए बिना, हम कह सकते हैं कि "खराब" तरीका खराब है क्योंकि यह जावा डॉक्स में स्पष्ट रूप से निर्धारित है:
https://docs.oracle.com/javase/8/docs/api/java/util/ConcurrentModificationException.html
दूसरों के बीच में, (जोर मेरा):
" उदाहरण के लिए, आम तौर पर एक संग्रह को संशोधित करने के लिए एक धागे के लिए यह स्वीकार्य नहीं है, जबकि एक और धागा उस पर पुनरावृत्त होता है। सामान्य तौर पर, इन परिस्थितियों में पुनरावृत्ति के परिणाम अपरिभाषित होते हैं। कुछ Iterator कार्यान्वयन (सामान्य प्रयोजन संग्रह के सभी सहित) JRE द्वारा प्रदान किए गए कार्यान्वयन) इस अपवाद को फेंकना चुन सकते हैं यदि इस व्यवहार का पता चला है "(...)
" ध्यान दें कि यह अपवाद हमेशा इंगित नहीं करता है कि किसी वस्तु को समवर्ती रूप से एक अलग थ्रेड द्वारा संशोधित किया गया है। यदि एकल थ्रेड विधि आवृत्तियों का अनुक्रम जारी करता है जो किसी ऑब्जेक्ट के अनुबंध का उल्लंघन करता है, तो ऑब्जेक्ट इस अपवाद को फेंक सकता है। उदाहरण के लिए, यदि। एक थ्रेड सीधे एक संग्रह को संशोधित करता है, जबकि यह संग्रह में विफल-तेज़ पुनरावृत्ति के साथ पुनरावृत्ति करता है, पुनरावृत्तिकर्ता इसके अपवाद को फेंक देगा। "
अधिक विवरणों में जाने के लिए: एक वस्तु जिसे फॉरएप लूप में इस्तेमाल किया जा सकता है, उसे "java.lang.Iterable" इंटरफ़ेस ( यहां javadoc ) को लागू करने की आवश्यकता है । यह एक Iterator (इस इंटरफ़ेस में पाया गया "Iterator" विधि के माध्यम से) पैदा करता है , जो कि मांग पर तुरंत दिया जाता है, और आंतरिक रूप से Iterable ऑब्जेक्ट का संदर्भ होगा जिसमें से इसे बनाया गया था। हालाँकि, जब एक forterach लूप में एक Iterable ऑब्जेक्ट का उपयोग किया जाता है, तो इस पुनरावृत्त का उदाहरण उपयोगकर्ता के लिए छिपा होता है (आप इसे किसी भी तरह से स्वयं एक्सेस नहीं कर सकते हैं)।
यह इस तथ्य के साथ युग्मित है कि एक Iterator बहुत ही स्टेटफुल है, अर्थात इसका जादू करने के लिए और इसके "अगले" और "hasNext" तरीकों के लिए सुसंगत प्रतिक्रियाएं हैं, इसके लिए यह आवश्यक है कि बैकिंग ऑब्जेक्ट को पुनरावृत्ति करने वाले की तुलना में किसी और चीज़ से नहीं बदला जाए। जबकि यह पुनरावृत्ति कर रहा है, इसे बनाता है ताकि यह अपवाद को फेंक दे जैसे ही यह पता चलता है कि बैकिंग ऑब्जेक्ट में कुछ बदल गया है, जबकि यह इसके बारे में पुनरावृत्ति कर रहा है।
जावा इस "फेल-फास्ट" पुनरावृत्ति को कहता है: यानी कुछ क्रियाएं हैं, आमतौर पर वे जो एक Iterable उदाहरण को संशोधित करते हैं (जबकि एक Iterator इस पर पुनरावृत्ति कर रहा है)। "फेल-फास्ट" धारणा का "असफल" हिस्सा एक आईटर की क्षमता को संदर्भित करता है ताकि यह पता लगाया जा सके कि इस तरह की "विफल" कार्रवाई कब होती है। "विफल-तेज़" (", जिसे मेरी राय में" सर्वश्रेष्ठ-प्रयास-तेज़ "कहा जाना चाहिए) का" तेज़ "हिस्सा, समवर्तीमॉडिफिकेशन अपवाद के माध्यम से पुनरावृत्ति को समाप्त कर देगा जैसे ही यह पता लगा सकता है कि" विफल "कार्रवाई होता है।