java - जावा में फ़ोरैच लूप में कॉलिंग को हटाएं




loops iterator (8)

  1. इसे आज़माएं 2. और स्थिति को "विंटर" में बदलें और आप आश्चर्यचकित होंगे:
public static void main(String[] args) {
  Season.add("Frühling");
  Season.add("Sommer");
  Season.add("Herbst");
  Season.add("WINTER");
  for (String s : Season) {
   if(!s.equals("Sommer")) {
    System.out.println(s);
    continue;
   }
   Season.remove("Frühling");
  }
 }

जावा में, क्या फ़ोरैच लूप का उपयोग करके संग्रह के माध्यम से पुनरावृत्ति करते समय संग्रह पर निकालना कानूनी है? उदाहरण के लिए:

List<String> names = ....
for (String name : names) {
   // Do something
   names.remove(name).
}

एक परिशिष्ट के रूप में, क्या उन वस्तुओं को हटाने के लिए कानूनी है जो अभी तक पुन: सक्रिय नहीं हुए हैं? उदाहरण के लिए,

//Assume that the names list as duplicate entries
List<String> names = ....
for (String name : names) {
    // Do something
    while (names.remove(name));
}

"लूप के लिए वर्धित" का जावा डिज़ाइन कोडर को कोडर को बेनकाब नहीं करना था, लेकिन किसी आइटम को सुरक्षित रूप से निकालने का एकमात्र तरीका इटरेटर तक पहुंचना है। तो इस मामले में आपको इसे पुराना स्कूल करना है:

 for(Iterator<String> i = names.iterator(); i.hasNext();) {
       String name = i.next();
       //Do Something
       i.remove();
 }

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

संपादित करें (पुनः परिशिष्ट): नहीं, iterator.remove () विधि के बाहर किसी भी तरह से सूची को बदलने के दौरान समस्याएं उत्पन्न होती हैं। इसके आसपास एकमात्र तरीका CopyOnWriteArrayList का उपयोग करना है, लेकिन यह वास्तव में समवर्ती मुद्दों के लिए है।

डुप्लिकेट को हटाने के लिए सबसे सस्ता (कोड की रेखाओं के संदर्भ में) सूची को एक लिंक्ड हैशसेट में डंप करना है (और फिर यदि आपको आवश्यकता हो तो सूची में वापस)। यह डुप्लिकेट को हटाते समय सम्मिलन आदेश को संरक्षित करता है।


उपयोग

इंटरमीटर के .remove ()

उपयोग

CopyOnWriteArrayList


एक संग्रह से सुरक्षित रूप से इसे हटाने के लिए इसे हटाने के लिए आपको एक इटरेटर का उपयोग करना चाहिए।

उदाहरण के लिए:

List<String> names = ....
Iterator<String> i = names.iterator();
while (i.hasNext()) {
   String s = i.next(); // must be called before you can call i.remove()
   // Do something
   i.remove();
}

जावा दस्तावेज़ीकरण से :

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

शायद कई नौसिखियों के लिए अस्पष्ट क्या तथ्य यह है कि फॉरवर्ड / फोरैच संरचनाओं का उपयोग करके एक सूची में पुनरावृत्ति करना पूरी तरह से एक पुनरावर्तक बनाता है जो अनिवार्य रूप से पहुंच योग्य नहीं है। यह जानकारी here मिल सकती here


जो लोग कहते हैं कि आप इटरेटर के अलावा किसी संग्रह से किसी आइटम को सुरक्षित रूप से हटा नहीं सकते हैं, वे बिल्कुल सही नहीं हैं, आप इसे समवर्ती संग्रह जैसे ConcurrentHashMap का उपयोग करके सुरक्षित रूप से कर सकते हैं।


मुझे इटरेटर के बारे में पता नहीं था, हालांकि आज मैं एक लूप के अंदर सूची से तत्वों को निकालने के लिए क्या कर रहा था:

List<String> names = .... 
for (i=names.size()-1;i>=0;i--) {    
    // Do something    
    names.remove(i);
} 

यह हमेशा काम कर रहा है, और अन्य भाषाओं या structs में इस्तेमाल किया जा सकता है जो iterators का समर्थन नहीं कर रहा है।


हां आप प्रत्येक लूप के लिए उपयोग कर सकते हैं, ऐसा करने के लिए आपको आइटम्स को हटाने के लिए एक अलग सूची बनाए रखना है और फिर removeAll() विधि का उपयोग कर नाम सूची से उस सूची को हटा दें,

List<String> names = ....

// introduce a separate list to hold removing items
List<String> toRemove= new ArrayList<String>();

for (String name : names) {
   // Do something: perform conditional checks
   toRemove.add(name);
}    
names.removeAll(toRemove);

// now names list holds expected values

for (String name : new ArrayList<String>(names)) {
    // Do something
    names.remove(nameToRemove);
}

जब आप मूल सूची से हटाते हैं तो आप सूची के names को क्लोन करते हैं और क्लोन के माध्यम से पुनरावृत्ति करते हैं। शीर्ष उत्तर की तुलना में थोड़ा क्लीनर।





foreach