面试回答
我们知道,在 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());
}