面试回答

我们知道,在 foreach 的同时修改集合,会触发 fail-fast 机制,要避免 fail-fast 机制,有如下处理方案:

1.通过普通的 for 循环

    public void listRemove() {
        List<Student> students = this.getStudents();
        for (int i = 0; i < students.size(); i++) {
            if (students.get(i).getAge() % 3 == 0) {
                Student student = students.get(i);
                students.remove(student);
            }
        }
    }

2.使用迭代器循环

    public void listRemove() {
        List<Student> students = this.getStudents();
        Iterator<Student> stuIter=students.listIterator();
        while (stuIter.hasNext()) {
            Student student=stuIter.next();
            if (student.getAge() % 3 == 0) {
                stuIter.remove();
            }
        }
    }

3.将原来的 copy 一份副本,遍历原来的 list,然后删除 副本(fail-safe)

    public void copyRemove() {
        // 注意,这种方法的 equals 需要重写
        List<Student> students = this.getStudents();
        List<Student> studentsCopy=deepclone(students);
        Iterator<Student> stuIter=students.listIterator();
        for(Student stu:students){
            if(neelDel(stu)){
                studentsCopy.remove(stu);
            }
        }
    }

4.使用并发安全的集合类

    public void cowRemove() {
        List<Student> students=new CopyOnWriteArrayList<>(this.getStudents());
        for(Student stu:students){
            if(stu.getAge()%2==0){
                students.remove(stu);
            }
        }
    }

5.通过 Stream 的过滤方法,因为 Stream 每次处理后都会生成一个新的 Stream,不存在并发问题,所以 Stream 的 filter 也可以修改 list 集合

    public List<Student> streamRemove() {
        List<Student> students = this.getStudents();
        return students.stream()
                .filter(item -> item.getAge() % 2 != 0)
                .collect(Collectors.toList());
    }
08-28 07:30