码迷,mamicode.com
首页 > 其他好文 > 详细

ArrayList源码讲解

时间:2021-02-18 13:31:47      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:分配   mat   bool   stat   ram   简单   ret   虚拟机   exce   

ArrayList源码

  1. 以ArrayList的add()方法为例

      /**
            * 新增元素操作
            */
           // eg1:第一次新增元素e="a1",
           public boolean add(E e) {
               /** 确定是否需要扩容,如果需要,则进行扩容操作*/
               ensureCapacityInternal(size + 1);  // Increments modCount!!
               // eg1:size=0,elementData[0]="a1",然后a自增为1
               elementData[size++] = e;
               return true;
           }
    
  2. 方法很简单,先扩容,再维护 size 变量 ,接着往里填元素。而添加方法中的扩容方法如下:

    // eg1:第一次新增元素,所以size=0,则:minCapacity=size+1=1,DEFAULT_CAPACITY=10
     private void ensureCapacityInternal(int minCapacity) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                // eg1:第一次新增元素,minCapacity取最大值10
                minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
            }
    
            ensureExplicitCapacity(minCapacity);
        }
    
  3. 此时可以发现方法中又调用了其他方法:继续跟踪

        /**
         * 确保明确的ArrayList的容量
         *
         * @param minCapacity ArrayList所需的最小容量
         */
        // eg1:第一次新增元素,minCapacity=10
        private void ensureExplicitCapacity(int minCapacity) {
            // eg1: modCount++后,modCount=1
            modCount++;
    
    
            /** 如果所需的最小容量大于elementData数组的容量,则进行扩容操作 */
            if (minCapacity - elementData.length > 0) { // eg1:10-0=10,满足扩容需求
                // eg1:minCapacity=10
                grow(minCapacity);
            }
        }
    
  4. 最后发现,真正的扩容操作在于 grow() 方法里:

     /**
         * Increases the capacity to ensure that it can hold at least the
         * number of elements specified by the minimum capacity argument.
         *
         * 扩容操作
         *
         * @param minCapacity 所需要的最小扩容量
         */
        // eg1:第一次新增元素,minCapacity=10,即:需要将elementData的0长度扩容为10长度。
        private void grow(int minCapacity) {
    
            /** 原有数组elementData的长度*/
            int oldCapacity = elementData.length; // eg1:oldCapacity=0
    
            /**
             * A >> 1 等于 A/2
             * eg: 3 >> 1 = 3/2 = 1
             *     4 >> 1 = 4/2 = 2
             * ------------------------
             * A << 1 等于 A*2
             * eg: 3 << 1 = 3*2 = 6
             *     4 << 1 = 4*2 = 8
             *
             * 000100 >> 1 = 000010
             * 000100 << 1 = 001000
             */
            /** 新增oldCapacity的一半整数长度作为newCapacity的额外增长长度 */
            int newCapacity = oldCapacity + (oldCapacity >> 1); // eg1:newCapacity=0+(0>>1)=0
    
            /** 新的长度newCapacity依然无法满足需要的最小扩容量minCapacity,则新的扩容长度为minCapacity */
            if (newCapacity - minCapacity < 0) {
                // eg1:newCapacity=10
                newCapacity = minCapacity;
            }
    
            /** 新的扩容长度newCapacity超出了最大的数组长度MAX_ARRAY_SIZE */
            if (newCapacity - MAX_ARRAY_SIZE > 0) {
                newCapacity = hugeCapacity(minCapacity);
            }
    
            /** 扩展数组长度为newCapacity,并且将旧数组中的元素赋值到新的数组中 */
            // eg1:newCapacity=10, 扩容elementData的length=10
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    
  5. hugeCapacity() 方法解析:

    /**
         * The maximum size of array to allocate.
         * Some VMs reserve some header words in an array.
         * Attempts to allocate larger arrays may result in
         * OutOfMemoryError: Requested array size exceeds VM limit
         *
         * 要分配的数组的最大大小。一些vm在数组中保留一些头字。
         * 尝试分配较大的数组可能会导致OutOfMemory错误:请求的数组大小超过了虚拟机限制
         */
        // MAX_ARRAY_SIZE=2147483639=01111111 11111111 11111111 11110111
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    
    //最大限度容量
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0)//溢出
            throw new OutOfMemoryError();
        //如若需要扩容的量大于了最大限制,则扩容量改为 int 最大限制量:2147483647。
        //否则为本类中所限制长度:2147483647-8
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
    }
    
  6. 总结

    技术图片

ArrayList源码讲解

标签:分配   mat   bool   stat   ram   简单   ret   虚拟机   exce   

原文地址:https://www.cnblogs.com/menghe123/p/14406996.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!