删除List集合中的元素你碰到过这样的陷阱吗?
删除List的三种方式:
(1) 普通遍历 :
1 @Test 2 public void testList(){ 3 ArrayList<String> list = new ArrayList<>(); 4 list.add("one"); 5 list.add("two"); 6 list.add("three"); 7 //1. 普通遍历删除 list 中元素 8 for (int i = 0; i < list.size(); i++) { 9 if (list.get(i).equals("one")){ 10 list.remove(i); 11 } 12 System.out.println(list.get(i)); 13 } 14 //result : 普通遍历:删除成功 15 }
(2) 增强for 循环:
1 @Test 2 public void testList(){ 3 ArrayList<String> list = new ArrayList<>(); 4 list.add("one"); 5 list.add("two"); 6 list.add("three"); 7 //2. 增强for循环 删除list中元素 8 for (String str : list){ 9 if (str.equals("one")){ 10 list.remove("one"); 11 } 12 System.out.println(str); 13 } 14 //result : 抛出异常 -> ConcurrentModificationException 15 }
(3) 迭代器遍历:
1 @Test 2 public void testList(){ 3 ArrayList<String> list = new ArrayList<>(); 4 list.add("one"); 5 list.add("two"); 6 list.add("three"); 7 //3. 迭代器遍历 删除 list中元素 8 Iterator<String> listIter = list.iterator(); 9 while (listIter.hasNext()){ 10 String next = listIter.next(); 11 if ("one".equals(next)){ 12 listIter.remove(); 13 } 14 System.out.println(next); 15 } 16 //result : 迭代器遍历 删除成功 17 } 18 }
总结:
(1)普通遍历 :在代码中,删除元素后,需要把下标减一。这是因为在每次删除元素后,ArrayList会将后面部分的元素依次往上挪一个位置(就是copy),所以,下一个需要访问的下标还是当前下标,所以必须得减一才能把所有元素都遍历完;<for循环适合删除特定一位元素,不适合循环删除特定元素>
(2)增强for循环:不能删除,抛出异常ConcurrentModificationException<list集合在使用中,对象不能发生改变,所以会抛出异常>;
(3)迭代器遍历:正常删除。
迭代器可以正常删除的原因:
迭代器删除元素时,是先使用next()获取元素,然后再remove()删除元素,但是如果next()和remove()之间,集合发生机构性变化(增加,删除)则会抛出IllegalStateException,是因为读完next(),迭代器的位置已经指向下一个,位置不再指向当前元素所在位置。
集合出现了结构性变化(删除或者是增加)则会出现异常IllegalStateException。