zoukankan      html  css  js  c++  java
  • list.remove的使用分析

    场景描述

    在做需求中,有很多情况会出现 对一个list遍历并过滤掉其中特定的数据 这种场景 。但是按照平常的使用方式,发现报错了。

    public static void main(String[] args) {
    String str1 = new String("abcde");
    String str2 = new String("abcde");
    String str3 = new String("abcde");
    String str4 = new String("abcde");
    String str5 = new String("abcde");
    List list = new ArrayList();
    list.add(str1);
    list.add(str2);
    list.add(str3);
    list.add(str4);
    list.add(str5);

    System.out.println("list.size()=" + list.size());
    for (int i = 0; i < list.size(); i++) {
    if (((String) list.get(i)).startsWith("abcde")) {
    list.remove(i);
    }
    }
    System.out.println("after remove:list.size()=" + list.size());
    }

      运行结果不是:

      list.size()=5

      after remove:list.size()=0

      居然是:

      list.size()=5

      after remove:list.size()=2

    原因:List每remove掉一个元素以后,后面的元素都会向前移动,此时如果执行i=i+1,则刚刚移过来的元素没有被读取。

    源码分析

    查看arrayList源码如下

        public E remove(int index); //执行删除指定位置的元素的功能
        public boolean remove(Object o)  //执行删除指定元素的功能
    

      remove(int index)在删除指定index位置时有以下3步

      • 先获取指定位置的元素用于返回值
      • 将指定位置以后的每个元素向前挪一位覆盖
      • 将数据最后一位 元素置空并将size减1
        public E remove(int index) {
    	RangeCheck(index);
    
    	modCount++;
    	E oldValue = (E) elementData[index];
    
    	int numMoved = size - index - 1;
    	if (numMoved > 0)
    	    System.arraycopy(elementData, index+1, elementData, index,
    			     numMoved);
    	elementData[--size] = null; // Let gc do its work
    
    	return oldValue;
        }

    remove(Object o)  

      判断object o 是否为null 如果为null 用 ==来判断,如果不为null 用 equals来判断引用是否相同

      从第一个找到即删除并返回

        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;
        }
    
        /*
         * Private remove method that skips bounds checking and does not
         * return the value removed.
         */
        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; // Let gc do its work
        }
    

     

    删除 List 中的元素会产生两个问题:

    1. 删除元素后 List 的元素数量会发生变化;
    2. 对 List 进行删除操作可能会产生并发问题;

     

    解决方案

    倒过来遍历

      1.倒过来遍历list

      for (int i = list.size()-1; i > =0; i--) {

      if (((String) list.get(i)).startsWith("abcde")) {

      list.remove(i);

      }

      }

      2.每移除一个元素以后再把i移回来

      for (int i = 0; i < list.size(); i++) {

      if (((String) list.get(i)).startsWith("abcde")) {

      list.remove(i);

      i=i-1;

      }

      }

      3.使用iterator.remove()方法删除

      for (Iterator it = list.iterator(); it.hasNext();) {

      String str = (String)it.next();

      if (str.equals("chengang")){

      it.remove();

      }

      }

  • 相关阅读:
    Ubuntu学习
    Django之 Views组件
    Django之 admin组件
    Django之 Models组件
    Django之 url组件
    递归
    python 之 编码
    Python 之 Restful API设计规范
    Django之实现登录随机验证码
    git &github 快速入门
  • 原文地址:https://www.cnblogs.com/shoshana-kong/p/9260155.html
Copyright © 2011-2022 走看看