มีหลายวิธีในการสำรวจและลบองค์ประกอบในรายการหรือแผนที่และปัญหาจะเกิดขึ้นเมื่อใช้อย่างไม่เหมาะสม มาเรียนรู้จากบทความนี้ด้านล่าง
1. ลบองค์ประกอบในระหว่างการเดินทางรายการ
ใช้ดัชนีตัวห้อยดัชนี traversal
ตัวอย่าง: ลบ 2 ในรายการ
โมฆะคงที่สาธารณะหลัก (String [] args) {list <integer> list = new ArrayList <integer> (); list.add (1); list.add (2); list.add (2); list.add (3); list.add (4); สำหรับ (int i = 0; i <list.size (); i ++) {ถ้า (2 == list.get (i)) {list.remove (i); } system.out.println (list.get (i)); } system.out.println ("list =" + list.toString ()); -ผลลัพธ์ผลลัพธ์:
1234List = [1, 2, 3, 4]
คำถาม:
ผลการศึกษาแสดงให้เห็นว่ามีการลบเพียง 2 ครั้งและอีก 2 คนพลาด เหตุผลคือ: หลังจากลบ 2 ครั้งแรกจำนวนองค์ประกอบในชุดจะลดลง 1 และองค์ประกอบที่ตามมาจะถูกย้ายไปข้างหน้า 1 บิตส่งผลให้ 2 ครั้งที่สองพลาด
วิธีใช้สำหรับการสำรวจแบบวนรอบ
ตัวอย่าง:
โมฆะสาธารณะคงที่สาธารณะ ListIterator2 () {รายการ <teger> list = new ArrayList <integer> (); list.add (1); list.add (2); list.add (2); list.add (3); list.add (4); สำหรับ (ค่า int: list) {ถ้า (2 == ค่า) {list.remove (ค่า); } system.out.println (ค่า); } system.out.println (ค่า); } system.out.println ("list =" + list.toString ()); -ผลลัพธ์:
ข้อยกเว้นในเธรด "Main" 12java.util.concurrentModificationException ที่ java.util.arraylist $ ittr.checkforcomodification (แหล่งที่ไม่รู้จัก) ที่ java.util.arraylist $ ittr.next test.listiterator.main (listiterator.java:10)
ภาพประกอบ:
คำอธิบายของการแก้ไขพร้อมกัน exception ใน JDK:
public class ConcurrentModificationException extends
RuntimeException ข้อยกเว้นนี้จะถูกโยนลงเมื่อวิธีการตรวจจับการปรับเปลี่ยนที่เกิดขึ้นพร้อมกันของวัตถุ แต่ไม่อนุญาตให้มีการปรับเปลี่ยนดังกล่าว
ตัวอย่างเช่นเมื่อเธรดวนซ้ำในคอลเลกชันการปรับเปลี่ยนเชิงเส้นอื่นมักจะไม่ได้รับอนุญาตให้ทำ โดยปกติในกรณีเหล่านี้ผลลัพธ์ของการทำซ้ำไม่แน่นอน หากตรวจพบพฤติกรรมนี้การใช้งานตัววนซ้ำบางอย่าง (รวมถึงการใช้งานการรวบรวมทั่วไปทั้งหมดที่จัดทำโดย JRE) อาจเลือกที่จะโยนข้อยกเว้นนี้ ตัววนซ้ำที่ดำเนินการนี้เรียกว่าตัววนซ้ำอย่างรวดเร็วเนื่องจากตัววนซ้ำล้มเหลวอย่างรวดเร็วโดยไม่เสี่ยงต่อความเสี่ยงของพฤติกรรมที่ไม่แน่นอนโดยพลการในบางครั้งในอนาคต
หมายเหตุ : ข้อยกเว้นนี้ไม่ได้ระบุเสมอว่าวัตถุได้รับการแก้ไขพร้อมกันโดยเธรดอื่น หากเธรดเดี่ยวออกลำดับของวิธีการเรียกที่ละเมิดสัญญาของวัตถุวัตถุอาจส่งข้อยกเว้นนี้ ตัวอย่างเช่นหากเธรดแก้ไขคอลเลกชันโดยตรงเมื่อวนซ้ำในคอลเลกชันโดยใช้ตัววนซ้ำที่ล้มเหลวอย่างรวดเร็วตัววนซ้ำจะโยนข้อยกเว้นนี้
หมายเหตุ : พฤติกรรมความล้มเหลวอย่างรวดเร็วของตัววนซ้ำไม่สามารถรับประกันได้เพราะโดยทั่วไปแล้วมันเป็นไปไม่ได้ที่จะรับประกันได้อย่างหนักว่ามีการปรับเปลี่ยนที่เกิดขึ้นพร้อมกันหรือไม่ การดำเนินการล้มเหลวอย่างรวดเร็วจะทำให้ดีที่สุดในการโยน ConcurrentModificationException Exception ดังนั้นจึงผิดที่จะเขียนโปรแกรมที่ขึ้นอยู่กับข้อยกเว้นนี้เพื่อปรับปรุงความถูกต้องของการดำเนินการดังกล่าว วิธีที่ถูกต้องคือ: ConcurrentModificationException ควรใช้เพื่อตรวจจับข้อบกพร่องเท่านั้น
สำหรับแต่ละใน Java ใช้ตัววนซ้ำสำหรับการประมวลผล ตัววนซ้ำไม่อนุญาตให้ลบคอลเลกชันระหว่างการใช้ตัววนซ้ำ สิ่งนี้ทำให้ตัววนซ้ำต้องโยน ConcurrentModificationException
วิธีที่ถูกต้อง
ตัวอย่าง:
void listiteratoratoratoratornatornator3 () {list <integer> list = new ArrayList <integer> (); list.add (1); list.add (2); list.add (2); list.add (3); list.add (4); Iterator <Integer> it = list.iterator (); ในขณะที่ (it.hasnext ()) {ค่าจำนวนเต็ม = it.next (); if (2 == ค่า) {it.remove (); } system.out.println (ค่า); } system.out.println (ค่า); } system.out.println ("list =" + list.toString ()); -ผลลัพธ์:
12234List = [1, 3, 4]
2. ลบองค์ประกอบระหว่างการเดินทางแผนที่
ตัวอย่างของวิธีการที่ถูกต้อง:
โมฆะคงที่สาธารณะหลัก (สตริง [] args) {hashmap <string, string> map = new hashmap <string, string> (); map.put ("1", "test1"); map.put ("2", "test2"); map.put ("3", "test3"); map.put ("4", "test4"); // การเดินทางแบบเต็มรูปแบบของแผนที่สำหรับ (รายการ <สตริง, สตริง> รายการ: map.entryset ()) {system.out.printf ("คีย์: %s ค่า: %s/r/n", entry.getKey (), entry.getValue ()); } // ลบองค์ประกอบ iterator <map.entry <string, string >> it = map.entryset (). iterator (); ในขณะที่ (it.hasnext ()) {map.entry <string, string> entry = it.next (); สตริงคีย์ = entry.getKey (); int k = integer.parseint (คีย์); if (k%2 == 1) {system.out.printf ("ลบคีย์:%s ค่า:%s/r/n", key, entry.getValue ()); it.remove (); }} // แผนที่ Traverse แบบเต็มสำหรับ (รายการ <สตริง, สตริง> รายการ: map.entryset ()) {system.out.printf ("คีย์: %s ค่า: %s/r/n", entry.getKey (), entry.getValue ()); -ผลลัพธ์:
คีย์: 1 ค่า: test1key: 2 ค่า: test2key: 3 ค่า: test3key: 4 ค่า: test4delete key: 1 ค่า: test1delete คีย์: 3 ค่า: test3key: 2 ค่า: test2key: 4 ค่า: test4
สังเกต
แต่ยังมีสิ่งที่เราต้องใส่ใจเกี่ยวกับวิธี remove() ของตัววนซ้ำ:
วิธี remove() iterator.next() ()
ก่อนที่จะเรียกวิธี remove() วิธี next() จะต้องเรียกใช้ครั้งเดียว
คำอธิบายของวิธีการลบ () ใน JDK-API:
void remove() ลบองค์ประกอบสุดท้ายที่ส่งคืนโดยตัววนซ้ำออกจากคอลเลคชั่นที่ชี้ไปที่ตัววนซ้ำ (การดำเนินการเสริม) วิธีนี้สามารถเรียกได้เพียงครั้งเดียวต่อการโทรถัดไป หากตัววนซ้ำได้รับการแก้ไขด้วยวิธีอื่นนอกเหนือจากการเรียกใช้วิธีนี้เมื่อวนซ้ำพฤติกรรมของตัววนซ้ำจะคลุมเครือ
การโยน: UnsupportedOperationException - หากตัววนซ้ำไม่รองรับการดำเนินการ remove IllegalStateException - หากไม่ได้เรียกวิธี next หรือวิธี remove ได้รับการเรียกหลังจากการโทรครั้งสุดท้ายไปยังวิธี next
สรุป
ข้างต้นคือทั้งหมดที่เกี่ยวกับการลบองค์ประกอบในระหว่างการสำรวจรายการและแผนที่ ฉันหวังว่าเนื้อหาของบทความนี้จะช่วยในการศึกษาหรือทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร