文章目录
- 1、为什么删不干净
- 倒序删
- 迭代器
- lambda表达式删除
为什么说数组边for循环遍历边删除会出现删不干净的情况
1、为什么删不干净
先写一个例子:可以先猜一下控制台会打印出什么内容?
public class removeIterator {
public static void main(String[] args) {
//ArrayList的底层数据结构就是数组
List<String>list=new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
for(int i=0;i<list.size();i++){
list.remove(i);
}
System.out.println(list.toString());
}
}
公布答案:
可以看到,并没有全部移除掉(猜对没?)。那这是为什么呢?
一开始,list中是这样的:
当移除下标为0的元素后,index+1=1,而元素bbb及之后的元素都向前移动了一位,如下图:
接下来要移除index==1位置上的元素,也就是移除ccc,移除ccc后,ddd的下标变为1,而index+1=2,即不会移除ddd,所以最后list剩下了bbb和ddd:
那么如何才可以稳定的删除呢,总结了以下三种方法:
倒序删
倒序删不会出现上面例子中元素数组位置改变的情况。
public class removeIterator {
public static void main(String[] args) {
List<String>list=new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
for(int i=list.size()-1;i>=0;i--){
list.remove(i);
}
System.out.println(list.toString());
}
}
结果:
迭代器
使用 Iterator.remove() 方法
简单介绍一下这个方法:
- Collection接口实现了Iterable接口,实现了Iterable接口的类可以拥有增强for循环
- Iterator的remove()方法优势
如果知道删除项的准确位置,删除操作的开销小
不能对正在被遍历的集合进行改变(add,remove,clear等操作),但是可以调用iterator中的remove方法进行删除
public class removeIterator {
public static void main(String[] args) {
List<String>list=new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
Iterator<String> it = list.iterator();
while(it.hasNext()){
it.next();
it.remove();
}
System.out.println(list.toString());
}
}
-----结果-----
[]
注:如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,再调用remove都会报IllegalStateException。
lambda表达式删除
上面使用迭代器的方式虽然能够正常的删除列表中的元素,但是不够优雅,因为要写好几行的遍历代码,显得略臃肿。能不能只用一行代码完成这个功能呢?答案是可以的——使用Lambda表达式:
删除指定条件的元素:
public String getString(List<Integer> list) {
if (list == null || list.isEmpty()) {
return null;
}
list.removeIf(e -> isNotValid(e));
return list.stream().map(String::valueOf).collect(Collectors.joining(","));
}
private static Boolean isNotValid(Integer in) {
if (in == null) {//为空的为无效数字
return true;
}
return false;
}
//输入:[1,2,3,null,5,null,7]
//输出:"1,2,3,5,7"