美文网首页Java集合
java ArrayList和HashMap 扩容

java ArrayList和HashMap 扩容

作者: else05 | 来源:发表于2016-09-12 16:11 被阅读260次

    网上搜索"ArrayList扩容机制"可以找到很多内容,但是多看几遍博文后会发现有些文章描述的知识点不同步。这里可能的原因是JDK版本不同,JDK6和JDK7+的内容有所不同。

    • ArrayList
    • JDK6
    // JDK6的扩容机制
    public void ensureCapacity(int minCapacity) {  
        modCount++;  
        int oldCapacity = elementData.length;  
        if (minCapacity > oldCapacity) {  
            Object oldData[] = elementData;  
            int newCapacity = (oldCapacity * 3)/2 + 1;  
                if (newCapacity < minCapacity)  
                    newCapacity = minCapacity;  
          // minCapacity is usually close to size, so this is a win:  
          elementData = Arrays.copyOf(elementData, newCapacity);  
        }  
    }  
    
    // 默认容量大小是10
    public ArrayList() {  
        this(10);  
    } 
    
    • JDK7+
        private void grow(int minCapacity) {
            int oldCapacity = elementData.length;
    //  用位运算,相当于扩容1.5倍
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            if (newCapacity - minCapacity < 0)
                newCapacity = minCapacity;
            if (newCapacity - MAX_ARRAY_SIZE > 0)
                newCapacity = hugeCapacity(minCapacity);
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    
    /** JDK7+ 默认的容量表面上是0,其实还是10 
     *,只是使用懒加载,当使用add方法添加一个元素时,容量会被扩成10  ,
     *这算是一个优化,如果实例化后没有添加元素,容量是0,节约空间,否则为10
     */
        private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
        public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
    // 当添加元素时,这里有懒加载设置容量 ,
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
    
        ensureExplicitCapacity(minCapacity);
    }
    
    • HashMap
    • JDK7:

    暂没安装jdk7的环境,引用别人的结论:
    - 容量默认16,负载因子默认0.75
    - 当初次扩充为:数量大于容量时扩充;第二次及以后为:当数量大于容量 * 负载因子时扩充。

    • JDK8:(以后补充,有部分是位运算,自己还没完全明白JDK8中的具体情况)

    总结:

    • 扩容其实就是数组的复制,把旧数组复制到一个新的数组中,所有尽可能减少数组的扩容对性能的优化是有必要的。
    • 在知道数组容量的情况下应该在实例化时指定容量。

    参考:

    相关文章

      网友评论

        本文标题:java ArrayList和HashMap 扩容

        本文链接:https://www.haomeiwen.com/subject/igepettx.html