zoukankan      html  css  js  c++  java
  • ArrayList源码分析

    public class Test1 {
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("abc");
         list.add("hello");
         list.remove("abc"); } }

    这是最简单的一个添加操作,查看list.add源代码:

     /**
         * Appends the specified element to the end of this list.
         *
         * @param e element to be appended to this list
         * @return <tt>true</tt> (as specified by {@link Collection#add})
         */
        public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }

    其中size大小默认为0,所以传递过去的参数为1

    查看ensureCapacityInternal()源代码

    private void ensureCapacityInternal(int minCapacity) {
            if (elementData == EMPTY_ELEMENTDATA) {
                minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
            }
    
            ensureExplicitCapacity(minCapacity);
        }

    而现在elementData为[],EMPTY_ELEMENTDATA也为[],所以进入if中,DEFAULTY_CAPACITY默认为10,minCapacity为1,所以minCapacity最终值为10

    ensureExplicitCapacity源代码为:

     private void ensureExplicitCapacity(int minCapacity) {
            modCount++;
    
            // overflow-conscious code
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
        }

    当前elementData.length为0,所以进入if中直行grow(minCapacity)

     /**
         * Increases the capacity to ensure that it can hold at least the
         * number of elements specified by the minimum capacity argument.
         *
         * @param minCapacity the desired minimum capacity
         */
        private void grow(int minCapacity) {
            // overflow-conscious code
            int oldCapacity = elementData.length;
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            if (newCapacity - minCapacity < 0)
                newCapacity = minCapacity;
            if (newCapacity - MAX_ARRAY_SIZE > 0)
                newCapacity = hugeCapacity(minCapacity);
            // minCapacity is usually close to size, so this is a win:
            elementData = Arrays.copyOf(elementData, newCapacity);
        }

    最后将重新复制原数组以newCapacity为大小的elementData属组。此时elementData中的元素为[null,null,null,null,null,null,null,null,null,null]

    然后直行到最开始的代码 list.add("abc");

    这时elementData中的元素为[abc, null, null, null, null, null, null, null, null, null]



    接下来我们看看list.remove("abc")

     /**
         * Removes the first occurrence of the specified element from this list,
         * if it is present.  If the list does not contain the element, it is
         * unchanged.  More formally, removes the element with the lowest index
         * <tt>i</tt> such that
         * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
         * (if such an element exists).  Returns <tt>true</tt> if this list
         * contained the specified element (or equivalently, if this list
         * changed as a result of the call).
         *
         * @param o element to be removed from this list, if present
         * @return <tt>true</tt> if this list contained the specified element
         */
        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;
        }

    首先判断删除的元素是否为空,如果不为空那么执行fastRemove(index)

     /*
         * 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; // clear to let GC do its work
        }

    System.arraycopy(elementData, index+1, elementData, index,numMoved); elementData[--size] = null;
    其中System.arraycopy()的意思是:public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) src:源数组; srcPos:源数组要复制的起始位置; dest:目的数组; destPos:目的数组放置的起始位置; length:复制的长度。
    所以上面两句话的意思是将elementData中index之后的位置依次移动到前一个位置。效率非常低。



    我们看看add(index,element)方法

    /**
         * Inserts the specified element at the specified position in this
         * list. Shifts the element currently at that position (if any) and
         * any subsequent elements to the right (adds one to their indices).
         *
         * @param index index at which the specified element is to be inserted
         * @param element element to be inserted
         * @throws IndexOutOfBoundsException {@inheritDoc}
         */
        public void add(int index, E element) {
            rangeCheckForAdd(index);
    
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            System.arraycopy(elementData, index, elementData, index + 1,
                             size - index);
            elementData[index] = element;
            size++;
        }

    与remove方法很相似。涉及到数组的移动。

    所以ArrayList的添加和删除操作时,会涉及到数组的复制,这是个成本很高的操作。


    优点:

    ArrayList执行查询的速度是非常快的,因为底层采用的是数组,而数组是根据下标索引来执行查找的。

  • 相关阅读:
    PHP vscode+XDebug 远程断点调试服务器上的代码
    Wordpress 为用户或角色 role 添加 capabilities(权限)
    Wordpress 后台文章编辑区添加模板选择功能
    CentOS 7 编译安装最新版git
    WordPress 通过文章 URL 获取文章 ID
    Web 安全问题 rel="noopener nofollw"
    Wordpress 通过 post id 获取文章 url
    git放弃修改&放弃增加文件
    Wordpress 作者模板页中的自定义帖子类型分页问题
    PHP 删除 url 中的 query string
  • 原文地址:https://www.cnblogs.com/vincent4code/p/4795347.html
Copyright © 2011-2022 走看看