zoukankan      html  css  js  c++  java
  • ArrayList和Vector的扩容机制

    ArrayList和Vector都是继承了相同的父类和实现了相同的接口。如下

        public class Vector<E>  
            extends AbstractList<E>  
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable  
        {}  
          
        public class ArrayList<E> extends AbstractList<E>  
                implements List<E>, RandomAccess, Cloneable, java.io.Serializable  
        {}  
    

    两者之间我认为主要有两个却别。
    1、Vector中的public方法都添加了synchronized关键字,以确保方法同步。
    2、内部属性不同,这也是导致扩容方式不同的原因所在。

    我现在来说第二条,
    ArrayList有两个属性,存储数据的数组elementData,和存储记录数目的size。
    Vector有三个属性,存储数据的数组elementData,存储记录数目的elementCount,还有扩展数组大小的扩展因子capacityIncrement。

    先来看ArrayList的扩展方法 

        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;  
            elementData = (E[])new Object[newCapacity];  
            System.arraycopy(oldData, 0, elementData, 0, size);  
        }  
           }  
    

    重构下看起来更方便

        public void ensureCapacity(int minCapacity) {  
        modCount++;//父类中的属性,记录集合变化次数  
        int oldCapacity = elementData.length;  
        if (minCapacity > oldCapacity) {//扩容的条件,数组需要的长度要大于实际长度  
            Object oldData[] = elementData;  
            int newCapacity = ((oldCapacity * 3)/2 + 1)<minCapacity?minCapacity: ((oldCapacity * 3)/2 + 1);  
               elementData = (E[])new Object[newCapacity];  
            System.arraycopy(oldData, 0, elementData, 0, size);  
        }  
           }  
    

     可以看到,再满足扩容条件时,扩展后数组大小为((原数组长度*3)/2+1)与传递参数中较大者

    再看看Vector的扩容方法 

        public synchronized void ensureCapacity(int minCapacity) {  
            modCount++;//父类中的属性,记录集合变化次数  
            ensureCapacityHelper(minCapacity);  
            }  
         private void ensureCapacityHelper(int minCapacity) {  
            int oldCapacity = elementData.length;  
            if (minCapacity > oldCapacity) {//扩容的条件,数组需要的长度要大于实际长度  
                Object[] oldData = elementData;  
                int newCapacity = (capacityIncrement > 0) ?  
                (oldCapacity + capacityIncrement) : (oldCapacity * 2);  
                    if (newCapacity < minCapacity) {  
                newCapacity = minCapacity;  
                }  
                elementData = new Object[newCapacity];  
                System.arraycopy(oldData, 0, elementData, 0, elementCount);  
            }  
            }  
    

    可以看到,相对于ArrayList的扩容方法,这个方法被一分为2,老实说我更喜欢这样,方法的职责更加明确。

    int newCapacity = (capacityIncrement > 0) ?(oldCapacity + capacityIncrement) : (oldCapacity * 2);

    当扩容因子大于0时,新数组长度为原数组长度+扩容因子,否子新数组长度为原数组长度的2倍。

    if (newCapacity < minCapacity) {newCapacity = minCapacity;}

    将上面生成的新数组长度与传递的参数要求长度作比较,较大者为最终的新长度。 

  • 相关阅读:
    .NET设计模式系列文章《转》
    sharpwebmail邮件管理系统开源 下载及使用方法
    POJ 1949 DP?
    POJ 1948 DP
    POJ 1945 暴搜+打表 (Or 暴搜+判重)
    POJ 1944 并查集(模拟)
    POJ 3259 Wormholes SPFA判负环
    POJ 3268 Dijkstra+priority_queue或SPFA
    POJ 3299 模拟
    POJ 3342 树形DP+Hash
  • 原文地址:https://www.cnblogs.com/wuxiang/p/5328241.html
Copyright © 2011-2022 走看看