ArrayList 的remove
之前在项目中看到这样一段代码,大概的业务逻辑就是移除集合中的元素
List<String> list=new ArrayList<>();
//add
for (int i=0;i<list.size();i++){
//判断条件
if(list.get(i).equals("")){
list.remove(i);
}
}
看似简短的代码好像没什么毛病,其实这里面有一个坑。测试一下
List<String> list=new ArrayList<>();
list.add("1");
list.add("2");
list.add("2");
list.add("3");
for (int i=0;i<list.size();i++){
//判断条件
if(list.get(i).equals("2")){
list.remove(i);
}
}
System.out.println(list);
[1, 2, 3]
我们发现,其中元素“2”并没有移除干净,这是为什么呢?
我们知道ArrayList是一个动态数组,先看一下ArrayList的remove方法。
public E remove(int index) {
//检测参数是否下标越界
rangeCheck(index);
//记录变更次数
modCount++;
//即将被移除的元素
E oldValue = elementData(index);
//这个变量实际代表的意义是,实际remove操作是否需要改变数组的结构
//如果下标不是数组的最后一位元素,那么将改变数组的结构
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
原因找到了,原来在remove操作的时候改变了数组的结构,在遍历的时候遗漏了那些往前窜的元素。
解决办法
-倒序遍历
for (int i=list.size()-1;i>=0;i--){
//判断条件
if(list.get(i).equals("2")){
list.remove(i);
}
}
-java8新特性(产生一个新的集合)
List<String> collect = list.stream().filter(s -> {
return !s.equals("2");
}).collect(Collectors.toList());
-迭代器
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
if (iterator.next().equals("2")) {
iterator.remove();
}
}
-removeAll方法
list.removeAll(Collections.singletonList("2"));
[1, 3]

浙公网安备 33010602011771号