【面试】List能在遍历的时候删除元素吗?

近期面试遇到这样一个问题

List能在遍历的时候删除元素吗?

当时思考的使用普通或者增强for循环肯定会出问题,于是回答可以使用iterator迭代器进行删除。

又问实际开发过程中,你直接写一个迭代器吗?

对啊...相视无言

昨天一朋友跟我说他code review的时候,组长说他写的迭代器代码臃肿、恶心、low...

突然想到jdk1.8之后的新特性lambda表达式stream流(高端大气上档次)

完全可以用,下面附上几种方式对比以及存在的问题:

1.普通for遍历

List<String> list = new ArrayList();
list.add("1");
list.add("2a");
list.add("2b");
list.add("2c");
list.add("2d");
for (int i = 0; i < list.size(); i++) {
    if (list.get(i).startsWith("2")){
        list.remove(i);
    }
}
//sout[1, 2b, 2d]

删除某个元素之后,list集合发生变化,数据前移,"2a"索引为"1",删除之后后边的数据前移一位,但此时"1"索引已经遍历过了,会直接访问"2"索引即"2c",删掉"2c"后依旧存在相同问题,漏删"2d",存在严重的漏删问题。

2.增强for遍历(foreach)

List<String> list = new ArrayList();
list.add("1");
list.add("2a");
list.add("2b");
list.add("2c");
list.add("2d");
for (String s : list) {
    if (s.startsWith("2")){
        list.remove(s);
    }
}
//Exception in thread "main" java.util.ConcurrentModificationException

直接报ConcurrentModificationException,由于增强for底层用的是iterator迭代器,如果了解源码的话就会发现iterator的next和remove方法都调用了checkForComodifcation方法(点进去看源码)

 

 这个方法会判断modCount(集合修改次数)与expectedModCount(迭代器修改次数)是否相等,如果不相等,就会抛出异常。

而使用迭代器的删除方法就不会出现异常

3.iterator迭代器

使用迭代器remove方法,会同步两个修改次数,不会报异常,

List<String> list = new ArrayList();
list.add("1");
list.add("2a");
list.add("2b");
list.add("2c");
list.add("2d");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
    if (iterator.next().startsWith("2")){
        iterator.remove();
    }
}
//sout:[1]

4.lambda表达式

stream流式编程,利用一个简单的过滤.filter

List<String> list = new ArrayList();
list.add("1");
list.add("2a");
list.add("2b");
list.add("2c");
list.add("2d");
list = list.stream()
        .filter(str->!str.startsWith("2"))
        .collect(Collectors.toList());
//[1]

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

互联网民工小小王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值