使用List中的remove方法遇到的坑
Posted jonalin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用List中的remove方法遇到的坑相关的知识,希望对你有一定的参考价值。
场景...
remove方法
list中根据判断条件符合的就remove掉一个数据
public static void main(String[] args) { List<CaseHead> list=new ArrayList<CaseHead>(); CaseHead caseHead1=new CaseHead(); caseHead1.setCaseid("a"); CaseHead caseHead2=new CaseHead(); caseHead2.setCaseid("b"); CaseHead caseHead3=new CaseHead(); caseHead3.setCaseid("c"); CaseHead caseHead4=new CaseHead(); caseHead4.setCaseid("d"); CaseHead caseHead5=new CaseHead(); caseHead5.setCaseid("e"); list.add(caseHead1); list.add(caseHead2); list.add(caseHead3); list.add(caseHead4); list.add(caseHead5); List<String> list2=new ArrayList<String>(); list2.add("a"); list2.add("b"); for (int i = 0; i < list.size(); i++) { String caseid=list.get(i).getCaseid(); for (int j = 0; j <list2.size() ; j++) { String l=list2.get(j); if (caseid.equals(l)){ list.remove(i); } } } for (int a = 0; a < list.size(); a++) { System.out.println(list.get(a).getCaseid()); }}
结果是什么?
根据以上代码,希望得到的结果是 cde 但是运行结果是bcde那么问题来了为什么会得到一下结果呢?
先看一下list remove的源码
// 删除ArrayList指定位置的元素 public E remove(int index) { RangeCheck(index);//检查index是否超出list大小范围,否则抛出异常 modCount++; E oldValue = (E) elementData[index];//elementData是实现list的数组 int numMoved = size - index - 1;//当执行删除操作是后面的元素全部向前面移动一位 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; return oldValue; } // 删除ArrayList的指定元素 public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } //快速删除第index个元素 private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; }
源码可知,List在删除指定位置的对象时,执行删除操作是后面的元素全部向前面移动一位
因为,当你remove掉一个对象时,list的就少了一个 index 0的被remove了,之前index 1的数据就自动变为index 0了。arrayList是有顺序数组,从0开始。如果从前开始删除实际上就相当于跳着删除了。
解决办法1:
每次删除之后i--自动返回到上一个index开始
public static void main(String[] args) { List<CaseHead> list=new ArrayList<CaseHead>(); CaseHead caseHead1=new CaseHead(); caseHead1.setCaseid("a"); CaseHead caseHead2=new CaseHead(); caseHead2.setCaseid("b"); CaseHead caseHead3=new CaseHead(); caseHead3.setCaseid("c"); CaseHead caseHead4=new CaseHead(); caseHead4.setCaseid("d"); CaseHead caseHead5=new CaseHead(); caseHead5.setCaseid("e"); list.add(caseHead1); list.add(caseHead2); list.add(caseHead3); list.add(caseHead4); list.add(caseHead5); List<String> list2=new ArrayList<String>(); list2.add("a"); list2.add("b"); for (int i = 0; i < list.size(); i++) { String caseid=list.get(i).getCaseid(); for (int j = 0; j <list2.size() ; j++) { String l=list2.get(j); if (caseid.equals(l)){ list.remove(i); i--; } } } for (int a = 0; a < list.size(); a++) { System.out.println(list.get(a).getCaseid()); } }
第二种解决方法
倒着删除从后往前遍历删除,从index大的往index小的删
public static void main(String[] args) { List<CaseHead> list=new ArrayList<CaseHead>(); CaseHead caseHead1=new CaseHead(); caseHead1.setCaseid("a"); CaseHead caseHead2=new CaseHead(); caseHead2.setCaseid("b"); CaseHead caseHead3=new CaseHead(); caseHead3.setCaseid("c"); CaseHead caseHead4=new CaseHead(); caseHead4.setCaseid("d"); CaseHead caseHead5=new CaseHead(); caseHead5.setCaseid("e"); list.add(caseHead1); list.add(caseHead2); list.add(caseHead3); list.add(caseHead4); list.add(caseHead5); List<String> list2=new ArrayList<String>(); list2.add("a"); list2.add("b"); for (int i = list.size()-1; i >= 0; i--) { String caseid=list.get(i).getCaseid(); for (int j = 0; j <list2.size() ; j++) { String l=list2.get(j); if (caseid.equals(l)){ list.remove(i); } } } for (int a = 0; a < list.size(); a++) { System.out.println(list.get(a).getCaseid()); } }
结果如下:
以上是关于使用List中的remove方法遇到的坑的主要内容,如果未能解决你的问题,请参考以下文章
debug底层java代码,对list中的数据去重的正确姿势,及对比java list remove正确使用方法与错误使用