• ArrayList数组扩容方式(基于jdk1.8)


    ArrayList无参构造函数为:

    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    而DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个空数组,即无参ArrayList创建时内部初始容量为0,

    当向ArrayList中增加数据时,先检查elementData数组的大小,如果elementData数组已经无法在存放元素,需要进行扩容,具体的扩容方法为grow方法

    public boolean add(E e) {
        //检查elementData数组是否可以能够存放下一个元素,
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //这种情况是无参构造方法创建的ArrayList,增加数据时elementData扩容为DEFAULT_CAPACITY(该值为10)大小的数组,
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
    
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
    
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    grow方法实现如下,每次增加的容量为 原本容量的一半

    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);
    }

    测试程序如下:

    private static void testArrayList() throws Exception {
    List<String> list = new ArrayList<>();
    Field field = ArrayList.class.getDeclaredField("elementData");
    field.setAccessible(true);
    for (int i = 0; i < 100; i++) {
    Object[] data = (Object[]) field.get(list);
    int before = data.length;
    list.add(String.valueOf(i));
    data = (Object[]) field.get(list);
    int after = data.length;
    if (before != after) {
    System.out.println(String.format("增加第%s个元素时进行了扩容,原来内部数组大小为:%s,扩容后为:%s", i + 1, before, after));
    }
    }
    }

    测试结果如下:

    增加第1个元素时进行了扩容,原来内部数组大小为:0,扩容后为:10
    增加第11个元素时进行了扩容,原来内部数组大小为:10,扩容后为:15
    增加第16个元素时进行了扩容,原来内部数组大小为:15,扩容后为:22
    增加第23个元素时进行了扩容,原来内部数组大小为:22,扩容后为:33
    增加第34个元素时进行了扩容,原来内部数组大小为:33,扩容后为:49
    增加第50个元素时进行了扩容,原来内部数组大小为:49,扩容后为:73
    增加第74个元素时进行了扩容,原来内部数组大小为:73,扩容后为:109

    如果将ArrayList初始容量设置为5,即List<String> list = new ArrayList<>(5);

    测试结果如下:

    增加第6个元素时进行了扩容,原来内部数组大小为:5,扩容后为:7
    增加第8个元素时进行了扩容,原来内部数组大小为:7,扩容后为:10
    增加第11个元素时进行了扩容,原来内部数组大小为:10,扩容后为:15
    增加第16个元素时进行了扩容,原来内部数组大小为:15,扩容后为:22
    增加第23个元素时进行了扩容,原来内部数组大小为:22,扩容后为:33
    增加第34个元素时进行了扩容,原来内部数组大小为:33,扩容后为:49
    增加第50个元素时进行了扩容,原来内部数组大小为:49,扩容后为:73
    增加第74个元素时进行了扩容,原来内部数组大小为:73,扩容后为:109

  • 相关阅读:
    浅谈数据的离散化
    【ZOJ】3785 What day is that day? ——浅谈KMP在ACM竞赛中的暴力打表找规律中的应用
    【Python】iichats —— 命令行下的局域网聊天程序
    【Python】iiblogs ——命令行下的网页收藏夹
    【Python】iiacm_filemaker ——简易的.cpp文件创建即初始化脚本,ACMer专用
    【黑科技】读写优化
    【POJ】1330 Nearest Common Ancestors ——最近公共祖先(LCA)
    【HDU】1717 小数化分数2 ——计数原理
    【POJ】2318 TOYS ——计算几何+二分
    【HDU】4923 Room and Moor(2014多校第六场1003)
  • 原文地址:https://www.cnblogs.com/wushengwuxi/p/11674670.html
Copyright © 2020-2023  润新知