java循环删除集合数据_java中循环的几种方式以及删除集合中的指定数据

论坛 期权论坛 编程之家     
选择匿名的用户   2021-5-31 07:35   34   0

一、for

//for循环中删除数据 -- 方法有漏洞

private static void deleteAtFor() {

ArrayList array = new ArrayList<>();

array.add(4);

array.add(5);

array.add(5);

array.add(6);

for(int i=0;i

if(array.get(i).equals(5)){

array.remove(i);

}

}

System.out.println(array);

}

得到删除后的集合数据是:[4,5,6]

从结果可以看出,有一个等于5的数据没有呗被删除,

这是为什么呢?

当我们深究 for循环在集合中工作原理就可以理解,事实上,当删除一个元素时,后面元素的索引就会前进以为,如删除第一个索引为1的5的时候,此时下一个元素5的索引就变成了1,而此时for循环执行i++,对应索引的位置为2 而新的1索引上的值就不会在读取了,所以集合结果为[4,5,6],要解决这个问题很容易只需要在删除的同时把自增变量i减一,和改变后的索引对应上就好,即把 array.remove(i)改为 array.remove(i--)即可;

如下:

//for循环中删除数据 -- 正确方法

private static void deleteAtFor() {

ArrayList array = new ArrayList<>();

array.add(4);

array.add(5);

array.add(5);

array.add(6);

for(int i=0;i

if(array.get(i).equals(5)){

array.remove(i--);

}

}

System.out.println(array);

}

结果为[4,6],正确!

二、forEach

//foreach中删除数据

private static void deleteAtForeach() {

ArrayList array = new ArrayList<>();

array.add(4);

array.add(5);

array.add(5);

array.add(6);

for (Integer a:array) {

if (4==a){

array.remove(a);

}

}

}

结果如下:

601e2cf54139

图片.png

意思是迭代器并发修改异常,出现这个原因是 当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

首先java的foreach循环其实就是根据list对象创建一个Iterator迭代对象,用这个迭代对象来遍历list,相当于list对象中元素的遍历托管给了Iterator,你如果要对list进行增删操作,都必须经过Iterator,否则Iterator遍历时会乱,所以直接对list进行删除时,Iterator会抛出ConcurrentModificationException异常

foreach迭代ArrayList时,真的不能删除元素吗,其实删除倒数第二个元素的,具体什么我们就不在这里说明了,大家可以看下这个https://blog.csdn.net/GarfieldEr007/article/details/80260822

三、迭代器

//Iterator迭代器中删除数据

private static void deleteAtIterator() {

ArrayList array = new ArrayList<>();

array.add(4);

array.add(5);

array.add(5);

array.add(6);

Iteratoriterator = array.iterator();

while (iterator.hasNext()){

if (iterator.next().equals(5)){

iterator.remove();

}

}

System.out.println(array);

}

结果是:[4, 6] ;注意点:while里只能出现一次iterator.next(),不然结果会出错。

四、用流的方式

ArrayList array = new ArrayList<>();

array.add(4);

array.add(5);

array.add(5);

array.add(6);

array.stream().forEach(integer -> {

if(integer.equals(5)){

array.remove(integer);

}

});

System.out.println(array);

结果:

601e2cf54139

图片.png

stream流forEach循环也不能进行删除。具体原因不做深究,哈哈!

五、结论:

在只是遍历情况下,我们四种都可以用,在修改集合的情况下,不能用foreach和stream流forEach;

番外:

如果只是单纯的遍历的话,

从效率角度来看:For Each的效率差,stream流forEach和迭代器的效率也没有很好。for循环最优,因为ArrayList通过数组来实现,数组通过索引来定位的时间复杂度是O(1),1次就能定位到,所以效率非常高;

从代码编写量来看:stream是最简洁的,for循环是量最多的;

但是,我最想推荐的遍历方式是:stream

stream().forEach用的多线程方式,其调用线程池的时候必然会耗费更多的时间。但如果你在循环内要处理的事情很多,或者要循环调用远程接口/数据库的时候,无疑极大的提升了效率。

回顾编程的发展历史,我们不难发现一个规律,那就是先是从最初的C/C++演变到Java/.net,这是编程界的一大进步,因为我们不再关注于指针操作,比如在java中JVM虚拟机已经帮我们完成了相应的操作,由于这一进步,这付出的代价是执行效率会降低,但是带来的好处就在于加快了编程开发的速度。

当编程由Java/.net演变到JavaScript/PHP/Kotlin,这又是编程界的另一大进步,这意味着我们在编写程序时没有必要再关注于数据类型,而该数据类型是由相应的语言在运行时确定,这样,这又一次降低了程序的运行速度,但是相应的又提升了代码编写的效率,因而通过回顾历史我们不难得出如下结论:

在编写代码时,一定要以最简洁为原则,毕竟运行程序的硬件成本会随着时间的推移在不断降低,而程序员的薪资则不会。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP