bug场景:
list遍历删除元素
昨天,项目需求中要对一个list进行遍历删除满足条件的元素,然而用for循环正序遍历时,不能完全删除,从而引发bug,观察后记录下来
问题描述:
提示:list删除不彻底
测试对象
class Patient {
private String name;
private String outdate;
@Override
public String toString() {
return "Yizhu{" +
"name='" + name + '\'' +
", outdate='" + outdate + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getOutdate() {
return outdate;
}
public void setOutdate(String outdate) {
this.outdate = outdate;
}
public Patient(String name, String outdate) {
this.name = name;
this.outdate = outdate;
}
}
原代码(错误):
//向list添加数据
ArrayList<Patient>_patientInfos=new ArrayList();
_patientInfos.add(new Patient("1","2021-01-01"));
_patientInfos.add(new Patient("2",""));
_patientInfos.add(new Patient("3",""));
_patientInfos.add(new Patient("4","2021-01-01"));
_patientInfos.add(new Patient("5","2021-01-01"));
//一般正序遍历
for(int i=0;i<=_patientInfos.size()-1;i++){
if (_patientInfos.get(i).getOutdate()!=null ){
_patientInfos.remove(_patientInfos.get(i));
}
}
System.out.println(_patientInfos);
输出结果
原因分析:
提示:list漏删元素
在遍历时满足条件则remove掉此元素,list长度变化,for循环中i值将继续往后累计
举个栗子:如果下标i=0满足如图条件,list将删除掉下标为0的元素,此时list.size()=4,继续for循环,下一步i=1,此时原list中的第二个元素将变为新list的第一个元素,将判断新list中第二个元素是否满足条件,漏掉新list中第一个元素,and so on
解决方案:
发现这个问题的时候还挺严重的,被领导好多人喷,都是自己学艺不精,思索不周,赶紧爬起来修复排查,(慌得一批)
排查后发现有几种解决方案
迭代器遍历删除
//正确 可删除多个
Iterator<Patient> iterator = _patientInfos.iterator();
while (iterator.hasNext()) {
Patient patient = iterator.next();
if (patient.getOutdate() != null) {
iterator.remove();//使用迭代器的删除方法删除
}
System.out.println(_patientInfos);
}
输出结果
倒序删除
在倒序时,如果满足条件则删除,下标前移,即使list长度变化也不会有影响,满足需求
for(int i=_patientInfos.size()-1;i>=0;i--){
if (_patientInfos.get(i).getOutdate()!=null ){
_patientInfos.remove(_patientInfos.get(i));
}
}
输出结果
其他方法:
可以另外新建list,for中满足条件的放入新list中
遍历结束后,list.removeAll(新list);移除掉新list,效率较低
学无止境