zoukankan      html  css  js  c++  java
  • 分享知识-快乐自己:都说新的Arraylist 扩容是(1.5倍+1) 看了1.8的源代码发现不是这么回事

     都说新的Arraylist 扩容是(1.5倍+1) 看了1.8的源代码发现不是这么回事

    就用下面这段代码在jdk的三个版本运行看了下效果:

    import java.lang.reflect.Field;
    import java.util.ArrayList;
     
    public class ArrayListDemo {
     
        public static void main(String[] args) {
            ArrayList<Integer> list1 = new ArrayList<Integer>();
            Integer capacity = getCapacity(list1);// 获取容量
            int size = list1.size();
            System.out.println("list1的容量:" + capacity);
            System.out.println("list1的大小:" + size);
            System.out.println("----------------------------");
     
            ArrayList<Integer> list2 = new ArrayList<Integer>();
            list2.add(1);
            capacity = getCapacity(list2);// 获取容量,arraylist初始化容量是10
            size = list2.size();
            System.out.println("list2的容量:" + capacity);
            System.out.println("list2的大小:" + size);
            System.out.println("----------------------------");
     
            ArrayList<Integer> list3 = new ArrayList<Integer>();
     
            capacity = getCapacity(list3);// 获取容量,arraylist初始化容量是10
            for (int i = 0; i < 10; i++) {
                list3.add(i);
            }
            capacity = getCapacity(list3);
            size = list3.size();
            System.out.println("list3的容量:" + capacity);
            System.out.println("list3的大小:" + size);
            System.out.println("----------------------------");
     
            ArrayList<Integer> list4 = new ArrayList<Integer>();
            for (int i = 0; i < 11; i++) {
                list4.add(i);
            }
            capacity = getCapacity(list4);// 获取容量
            size = list4.size();
            System.out.println("list4的容量:" + capacity);
            System.out.println("list4的大小:" + size);
     
        }
     
        // 获取list容量
        public static Integer getCapacity(ArrayList list) {
            Integer length = null;
            Class clazz = list.getClass();
            Field field;
            try {
                field = clazz.getDeclaredField("elementData");
                field.setAccessible(true);
                Object[] object = (Object[]) field.get(list);
                length = object.length;
                return length;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return length;
        }
    }

    jdk1.6:运行结果

    list1的容量:10
    list1的大小:0
    ----------------------------
    list2的容量:10
    list2的大小:1
    ----------------------------
    list3的容量:10
    list3的大小:10
    ----------------------------
    list4的容量:16
    list4的大小:11

    部分源代码:

    public void ensureCapacity(int var1) {
        ++this.modCount;
        int var2 = this.elementData.length;
        if (var1 > var2) {
            Object[] var3 = this.elementData;
            int var4 = var2 * 3 / 2 + 1;
            if (var4 < var1) {
                var4 = var1;
            }
     
            this.elementData = Arrays.copyOf(this.elementData, var4);
        }
     
    }

    jdk1.7 :运行结果

    list1的容量:0
    list1的大小:0
    ----------------------------
    list2的容量:10
    list2的大小:1
    ----------------------------
    list3的容量:10
    list3的大小:10
    ----------------------------
    list4的容量:15
    list4的大小:11

    部分源代码:

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
    
        ensureExplicitCapacity(minCapacity);
    }
    
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
    
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    
    
    
    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);
    }

    jdk1.8:运行结果

    list1的容量:0
    list1的大小:0
    ----------------------------
    list2的容量:10
    list2的大小:1
    ----------------------------
    list3的容量:10
    list3的大小:10
    ----------------------------
    list4的容量:15
    list4的大小:11

    部分源码:

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    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);
    }
    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);
    }

    总结:

    发现不同jdk是不一样的,关于(1.5倍+1)出现在jdk1.6,其他1.7和1.8都是(1.5倍扩容)。

    关于 详细代码和原理可以参考 3。参考1和2也是不错的!

    参考  1: ArrayList扩容1.5倍

             2 :ArrayList源码解析

             3 :ArrayList初始默认容量(长度)

  • 相关阅读:
    ES6-Generator
    ES6-Iterator & for...of循环
    ES6-Proxy and Reflect
    在Main中定义student的结构体,进行年龄从大到小依次排序录入学生信息。(结构体的用法以及冒泡排序)
    函数的调用(取两个整型变量中的最大值)
    将一个字符串数组的元素的顺序进行翻转。。
    枚举类型练习
    利用Arraylist输入学生的成绩,求出平均分和总分。
    简单的推箱子游戏(利用数组)
    枚举类型的声明
  • 原文地址:https://www.cnblogs.com/mlq2017/p/10300112.html
Copyright © 2011-2022 走看看