1. 简介
有时候需要在集合遍历过程中进行增/删,下面介绍几种正确的操作方式。
2. 示例
例如有如下集合[1, 2, 2, 3, 5],需要删除被2整除的元素。
1 import java.util.*; 2 3 public class ListFunc2 { 4 5 public static void main(String[] args){ 6 String str = "12235"; 7 String[] arr = str.split(""); 8 List<String> list1 = new ArrayList<>(Arrays.asList(arr)); 9 List<String> list2 = new ArrayList<>(Arrays.asList(arr)); 10 List<String> list3 = new ArrayList<>(Arrays.asList(arr)); 11 List<String> list4 = new ArrayList<>(Arrays.asList(arr)); 12 List<String> list5 = new ArrayList<>(Arrays.asList(arr)); 13 List<String> list6 = new ArrayList<>(Arrays.asList(arr)); 14 15 System.out.println(list1); // [1,2,2,3,5]
2.1 正序方式
从集合的第一个元素开始遍历:
1 // 正序方式 2 for(int i=0; i<list2.size(); i++){ 3 int value = Integer.parseInt(list2.get(i)); 4 if(value%2==0){ 5 list2.remove(i); 6 } 7 } 8 System.out.println(list2); // [1, 2, 3 ,5]
发现未完全删除可以被2整除的元素,原因如下:当i=1时删除第二个元素2,此时后面的元素会前移;然而下次遍历时索引i=2,
对应的元素为3,跳过了原集合中的第三个元素2。
0 1 2 3 4 // index 1 2 2 3 5 1 2 3 5
此时尝试对索引进行修正,将索引重新指向原集合的第三个元素:
1 for(int i=0; i<list3.size(); i++){ 2 int value = Integer.parseInt(list3.get(i)); 3 if(value%2==0){ 4 list3.remove(i); 5 i--; // 修正 6 } 7 } 8 System.out.println(list3); // [1, 3, 5]
2.2 逆序方式
从集合的最后一个元素开始向前遍历:
1 // 逆序方式 2 for(int i= list4.size()-1; i>=0; i--){ 3 int value = Integer.parseInt(list4.get(i)); 4 if(value%2==0){ 5 list4.remove(i); 6 } 7 } 8 System.out.println(list4); // [1, 3, 5]
索引和集合的对应变化过程如下:
当索引为2时,删除集合中的第三个元素2,此时集合中的后续元素前移;然后索引变为1,删除集合中的第二个元素2;
可以发现,后续元素的前移不会导致索引的跳跃,不影响前面的元素。
0 1 2 3 4 // index 1 2 2 3 5 1 2 3 5
2.3 Iterator方式
推荐使用Iterator对遍历过程中的集合进行修改,不用担心索引的跳跃和越界情况。
1 // iterator迭代器 2 for(Iterator<String> it = list5.iterator(); it.hasNext();){ 3 int value = Integer.parseInt(it.next()); 4 if(value%2==0){ 5 it.remove(); 6 } 7 } 8 System.out.println(list5); // [1, 3, 5] 9 10 Iterator<String> it = list6.iterator(); 11 while(it.hasNext()){ 12 int value = Integer.parseInt(it.next()); 13 if(value%2==0){ 14 it.remove(); 15 } 16 } 17 System.out.println(list6); // [1, 3, 5]
2.4 Java 8 新特性
直接使用boolean removeIf(Predicate<? super E> filter)方法
1 // java 8最新方法 2 list1.removeIf(v->Integer.parseInt(v)%2==0); // v表示集合中的元素,给出适当条件过滤 3 System.out.println(list1); // [1, 3, 5]
!!!