Java中的List集合无法初始化容量
我们都知道Java的List集合是有进行一个懒加载的优化的,当你没有在集合里面存放元素的时候,集合的size为0
可我记得List集合是可以指定大小的,于是我写了一段代码去进行测试

我这个时候就非常疑惑,我不是指定了大小吗?为什么size还是0?
想不明白,我就开始翻源码看看
原来size是记录的集合里面的元素个数,而不是集合的容量大小
- 
先看空参构造器 从这段代码我们可以看得出懒加载机制,当没有往集合中放任何东西 的时候,就会初始化一个{} 
            
            
              java
              
              
            
          
          		private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
		transient Object[] elementData;
		public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }- 再看看add()源码
            
            
              java
              
              
            
          
          		public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 添加到集合之前先把判断一下当前容量size + 1是否会超出容量大小
        elementData[size++] = e;
        return true;
    }
		private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
		private static final int DEFAULT_CAPACITY = 10;
		private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
          	// 这里开始判断了,如果说你是第一次初始化,即集合为{}的话,我就会给你分配 DEFAULT_CAPACITY = 10
          	// 需要注意的是这里并没有把 size的值设置为10,size只记录集合里面有多少元素,而不是集合容量
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity; // 如果说你不是第一次添加了,就返回当前的容量 + 1的值
        // 这个地方有点绕,需要看传参 add方法里面的 ensureCapacityInternal(size + 1) 这个size + 1 就是minCapacity
    }
		private void ensureExplicitCapacity(int minCapacity) {
        modCount++; // 这里的modCount先不用管,因为ArrayList线程不安全,当modCount和expectModCount不一致就会抛异常
        // 当这个minCapacity大于数组长度的时候,也就意味着数组放不下了,这个时候就需要扩容了
        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);
        // 从源码我们可以看出,ArrayList集合底层的扩容机制就是通过数组的复制
        elementData = Arrays.copyOf(elementData, newCapacity);
    }- 说点题外话,ArrayList集合是如何扩容的,拆分一下grow源码
            
            
              java
              
              
            
          
          int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);这里可以看到newCapacity会把你原来集合的大小加上你原来集合大小的一半来进行扩容,就是1.5倍扩容,这是第一次
第二次扩容是什么时候呢?
            
            
              java
              
              
            
          
           if (newCapacity - minCapacity < 0)
     newCapacity = minCapacity;当第一次扩容结束后,发现还是放不下,就会按照你给的集合大小来扩容了
当发现扩容后的大小超出了 MAX_ARRAY_SIZE 就会把整数的最大值给你了 Integer.MAX_VALUE
            
            
              java
              
              
            
          
          		private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 		if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
     
		private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
    }总结
经过这次奇怪的尝试,终于搞清楚了size到底是什么了
我如果想要初始化List集合,就不能初始化集合容量 ,而是初始化集合的size

也就是说,如果想要真正的初始化这个size,就必须要往集合里面添加元素才能改变这个size属性