使用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方法遇到的坑的主要内容,如果未能解决你的问题,请参考以下文章

Arrays.asList中所遇到的坑

List遍历时删除遇到的问题

debug底层java代码,对list中的数据去重的正确姿势,及对比java list remove正确使用方法与错误使用

ArrayList的subList方法带来的坑

java Stack pop返回值作为list.remove参数遇到问题

List中remove()方法移除不了数据,达人快来~