Java使用for循环删除集合元素需要避免的犯错

136 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

最近写Java代码使用for循环遍历集合并在其中删除满足条件的元素时,发现集合明明有5个元素,遍历却不足5次,经过排查后发现是自己犯了一个不该犯的错误,就是在for循环中删除了一个元素后,下次遍历的集合size已经-1了,而用来遍历计数的变量i在上次的循环中已经+1,从而导致循环次数不足集合的原始长度。

问题重现例子,删除集合里的3:

public class CollectionTest {
	
	public static void main(String[] args) {
		Integer[] intArray = new Integer[]{1, 2, 3, 3, 4, 5, 6, 7, 8, 9};
		List<Integer> intList = new ArrayList<Integer>(Arrays.asList(intArray));
		System.out.println("删除前:"+intList);
		System.out.println("size:"+intList.size());
		
		for (int i = 0; i < intList.size(); i++){
			if (intList.get(i) == 3){
				intList.remove(i);
			}
		}
			
		System.out.println("删除后:"+intList);
		System.out.println("size:"+intList.size());
	}
}

运行结果:

删除前:[1, 2, 3, 3, 4, 5, 6, 7, 8, 9]
size:10
删除后:[1, 2, 3, 4, 5, 6, 7, 8, 9]
size:9

可以看到,这样写并没有达到开始的目的,集合中仍有3。

解决这个问题最简单的方法就是在删除元素之后将变量i--,这样就和前面的i++抵消了,下次循环不会跳过第2个3,从而删除满足条件的元素:

public class CollectionTest {
	
	public static void main(String[] args) {
		Integer[] intArray = new Integer[]{1, 2, 3, 3, 4, 5, 6, 7, 8, 9};
		List<Integer> intList = new ArrayList<Integer>(Arrays.asList(intArray));
		System.out.println("删除前:"+intList);
		System.out.println("size:"+intList.size());
		
		for (int i = 0; i < intList.size(); i++){
			if (intList.get(i) == 3){
				intList.remove(i);
				i--;
			}
		}
		
		System.out.println("删除后:"+intList);
		System.out.println("size:"+intList.size());
	}
}

运行结果:

删除前:[1, 2, 3, 3, 4, 5, 6, 7, 8, 9]
size:10
删除后:[1, 2, 4, 5, 6, 7, 8, 9]
size:8

除了这个方法以外,还可以通过迭代器来实现:

public class CollectionTest {
	
	public static void main(String[] args) {
		Integer[] intArray = new Integer[]{1, 2, 3, 3, 4, 5, 6, 7, 8, 9};
		List<Integer> intList = new ArrayList<Integer>(Arrays.asList(intArray));
		System.out.println("删除前:"+intList);
		System.out.println("size:"+intList.size());
		
		Iterator<Integer> it = intList.iterator();
		while(it.hasNext()){
			if (it.next() == 3){
				it.remove();
			}
		}
		
		System.out.println("删除后:"+intList);
		System.out.println("size:"+intList.size());
	}
}

运行结果:

删除前:[1, 2, 3, 3, 4, 5, 6, 7, 8, 9]
size:10
删除后:[1, 2, 4, 5, 6, 7, 8, 9]
size:8