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

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

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

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

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

对啊...相视无言

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

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

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

1.普通for遍历

List 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 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方法(点进去看源码)

【面试】List能在遍历的时候删除元素吗?_第1张图片 

【面试】List能在遍历的时候删除元素吗?_第2张图片

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

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

3.iterator迭代器

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

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

4.lambda表达式

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

List 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]

你可能感兴趣的:(面试,java,面试,list)