慎用在循环中进行删除(js,java通用)

正经学徒,佛系记录,不搞事情

JS for循环与$.each循环

 JS for(通过下标)

var arr = [0,1,2,3,4,5];
console.log("原数组"+arr);
for(var i=0; i<arr.length; i++){
	console.log("当前item:"+arr[i]);
	if(i == 1){
		arr.splice(i,1);
	}
}
console.log("现数组"+arr);

上面的操作目的是为了删除数组中的1,结果如下

从原数组和现数组的比较来看,确实成功的删除了1,但是出问题的地方却是在循环的过程中:

  • 第一遍循环输出 当前item:0 没问题
  • 第二遍循环输出 当前item:1 并且删除了1 没问题
  • 第三遍循环输出 当前item:3 出现了问题,这里应该输出2才对,为什么2被跳过了

原因是:当执行到1时,开始删除数组元素1,删除成功时,后面的元素将会顶上去,这就导致了当前1的位置被2顶替了,而循环还在继续,i还在自增,导致跳过了元素2

这种在特殊需求下将会出现问题,例如删除数组中所有为2的值

var arr = [0,2,2,4,2,5];
console.log("原数组"+arr);
for(var i=0; i<arr.length; i++){
	console.log("当前item:"+arr[i]);
	if(arr[i] == 2){
		arr.splice(i,1);
	}
}
console.log("现数组"+arr);

结果是删除了第一个2,跳过了第二个2,而后面继续循环到下一个2进行删除,问题就出现在了第二个2由于在第一个2的下一个,导致被跳过

这里提供一个最简单也最已读的解决方式:

var arr = [0,2,2,4,2,5];
console.log("原数组"+arr);
for(var i=0; i<arr.length; i++){
	console.log("当前item:"+arr[i]);
	if(arr[i] == 2){
		arr.splice(i,1);
		i--;//重点代码
	}
}
console.log("现数组"+arr);

既然数组会往上顶,而i还在自增,那就在元素删除的时候将i自减归位

JS $.each

var arr = [0,1,2,3,4,5];
console.log("原数组"+arr);
$.each(arr,function(index,item){
	console.log("当前item:"+item);
	if(item == 1){
		arr.splice(index,1);
	}
});
console.log("现数组"+arr);

首先跳过被删除的下一个元素,这个与for效果一样,但会有另外一个问题,即循环次数的问题

看jquery $.each的源码可知,在each内部已经将初始的数组长度保存下来了,所以建议不要使用each删减数组元素

java for 通过下标和迭代器

JAVA for(通过下标)

List<String> list = new ArrayList<>(Arrays.asList("0","1","2","3","4"));
System.out.println("原数组:"+list.toString());
for(int i=0; i<list.size(); i++){
    System.out.println("当前item:"+list.get(i));
    if("1".equals(list.get(i))){
        list.remove(i);
    }
}
System.out.println("现数组:"+list.toString());

问题原因及解决方法同 JS for(通过下标)

List<String> list = new ArrayList<>(Arrays.asList("0","1","2","3","4"));
System.out.println("原数组:"+list.toString());
for(int i=0; i<list.size(); i++){
    System.out.println("当前item:"+list.get(i));
    if("1".equals(list.get(i))){
        list.remove(i);
        i--;//关键代码
    }
}
System.out.println("现数组:"+list.toString());

JAVA 迭代

迭代有两种情况,第一种在循环的时候使用list.remove方法删除元素,这种情况将会直接报错,网上已有很多关于这个错误的原因,关键词是集合内的modCount(几乎所有的非线程安全的集合都会使用这种方式)

List<String> list = new ArrayList<>(Arrays.asList("0","1","2","3","4"));
System.out.println("原数组:"+list.toString());
for(Iterator<String> it = list.iterator(); it.hasNext();){
    String item = it.next();
    if("1".equals(item)){
        list.remove(item);
    }
}
System.out.println("现数组:"+list.toString());

 正确的方式是使用it.next().remove()来删除元素,如下

List<String> list = new ArrayList<>(Arrays.asList("0","1","2","3","4"));
System.out.println("原数组:"+list.toString());
for(Iterator<String> it = list.iterator(); it.hasNext();){
    String item = it.next();
    System.out.println("当前item:"+item);
    if("1".equals(item)){
        it.remove();
    }
}
System.out.println("现数组:"+list.toString());

猜你喜欢

转载自blog.csdn.net/qq_31748587/article/details/89914965