zoukankan      html  css  js  c++  java
  • ArrayList中remove方法和set(null)的区别

    在分析源码ArrayList.remove()时,偶然发现了一个疑惑的点,就是:源码也是将最后一个对象的引用指向null(源码:elementData[--size] = null; // clear to let GC do its work),而使用 list.set(最大下标,null)同样也是将对象的引用指向null,为什么输出的结果为:remove()方法 对应位置的值会被“删除”,set()方法 下标位置的值依然被保留、输出。这是为什么呢?

      首先我们先看一下remove()方法的源码,这里只讲通过下标删除。

       /**
         * Removes the element at the specified position in this list.
         * Shifts any subsequent elements to the left (subtracts one from their
         * indices).
         *
         * @param index the index of the element to be removed
         * @return the element that was removed from the list
         * @throws IndexOutOfBoundsException {@inheritDoc}
         */
        public E remove(int index) {
            // 检查下标是否越界
            rangeCheck(index);
    
            // 记录修改次数,这里就是foreach、Iterator遍历时不能执行删除的根本原因
            modCount++;
            E oldValue = elementData(index);
    
            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;
        }

      这里我准备了一个事例用来分析,如下:

        @Test
        public void Test1() {
            String[] array = {"1111","2222","3333","4444","5555"};
            List<String> setList = new ArrayList<>(Arrays.asList(array));
            List<String> removeList = new ArrayList<>(setList);
    
            setList.set(4, null);
            removeList.remove(4);
    
            System.out.println(setList);
            System.out.println(removeList);
        }

      输入结果:

    通过分析查找资料,终于发现了问题出在哪了,原来源码中的 --size 就是造成两种结果的原因,下面给出解析:

      1:首先要明白一个道理,数据存储在内存中是连续的。

      其次,集合在 AbstractCollection 重写了toString方法,可以看到 arrayList 是通过迭代器遍历输出的。

      

      2:ArrayList实现了  iterator()  方法,返回一个实现  Iterator<E>  的内部类  Itr ,其中  hasNext()  方法 决定了只返回size大小的数据,而size 正是arrayList的大小

      

    现在,知道为什么输出的结果会是上面看到的样子了吧。其实,上面两种方式生成的数组,存储在内存中是一样的,都是最后一个对象的引用指向null,只是 remove()方法 改变了记录数组的size大小。

    本文作学习交流用,如有错误,欢迎指正!
  • 相关阅读:
    剑指offer51-正则表达式匹配
    剑指offer50-构建乘积数组
    剑指offer49-数组中的重复
    PHP系列笔记——Zend_Controller工作流程
    多态与重载
    读取文件数据的大概流程
    基于HTTP协议下载文件的实现
    C++中的面向对象笔记
    firebreath注册接口
    python读取excelxlsx,写入excel
  • 原文地址:https://www.cnblogs.com/pan1042/p/11271118.html
Copyright © 2011-2022 走看看