zoukankan      html  css  js  c++  java
  • 使用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());
            }
    }

    结果如下:

  • 相关阅读:
    软件版本具体代表什么意思
    面向接口的编程
    MySQL mysqldump用法
    常见问答解答
    Perl 语言笔记
    JAVA 基础知识
    面向接口编程的基本原则
    判断文件存在与否【Linux】
    Gtk Label设置字体颜色
    解压缩路径设置【Linux】
  • 原文地址:https://www.cnblogs.com/JonaLin/p/13236802.html
Copyright © 2011-2022 走看看