• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

奋斗的软件工程师

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

ArrayList集合的底层原理

①利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组

②添加第一个元素时,底层会创建一个新的长度为10的数组

③存满时,会扩容1.5倍

④如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准

点击查看代码
package com.itheima.javase;


import java.util.ArrayList;

/**
 * TODO: ArrayList集合的底层原理

 * ①利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组

 * ②添加第一个元素时,底层会创建一个新的长度为10的数组

 * ③存满时,会扩容1.5倍

 * ④如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准
 */

public class ArrayListDemo {
    public static void main(String[] args) {

        ArrayList<Integer> list = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            list.add(i);
        }

        list.add(-1);

    }
    /*
    ArrayList<Integer> list = new ArrayList<>();

    用无参构造器创建ArrayList集合,JVM自动调用public ArrayList(){}
    
    elementData是一个可以存储任意类型的对象的数组,并且这个变量在对象被序列化时不会被写入到输出流中。
    
    DEFAULTCAPACITY_EMPTY_ELEMENTDATA是ArrayList的私有静态常量数组,这个数组是空的,可以存储任意类型的对象。
    
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    
    至此,利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组,证毕
    
    for (int i = 0; i < 10; i++) {
        list.add(i);
    }
    
    当集合添加1个元素,会调用add()方法,随后会有一系列方法的嵌套调用,
    
    boolean add(E e)
    
    E是泛型(Integer) e是元素i
    
    add---------->ensureCapacityInternal---------->ensureExplicitCapacity(calculateCapacity(elementData, minCapacity))---------->grow(minCapacity)
    
    void ensureCapacityInternal(size + 1)
    
    因为size是ArrayList类的一个私有成员变量,初始值是0
    
    所以演变成void ensureCapacityInternal(1)
    
    记住,此时minCapacity=1
    
    void ensureCapacityInternal(int minCapacity)
    
    在方法ensureCapacityInternal中会调用ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    
    其中方法calculateCapacity(elementData, minCapacity)的返回值作为参数传入方法ensureExplicitCapacity中
    
    故先看方法calculateCapacity(elementData, minCapacity)
    
    elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA  [new ArrayList()已证]
    
    int calculateCapacity(Object[] elementData, int minCapacity){
    
    不难看出方法calculateCapacity的返回值是return Math.max(DEFAULT_CAPACITY, minCapacity);
    
    DEFAULT_CAPACITY是ArrayList类的一个常量,值为10
    
    即是ensureExplicitCapacity(10);
    
    void ensureExplicitCapacity(int minCapacity)中
    
    if (minCapacity - elementData.length > 0) 10-0>0条件为真
    
    进而调用grow(minCapacity);
    
    void grow(int minCapacity) {

        int oldCapacity = elementData.length;

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

    其中oldCapacity=0,newCapacity=0>>1,右移1位,还是0
    
    newCapacity - minCapacity=0-10=-10<0,条件为真,故newCapacity=10,最后执行elementData = Arrays.copyOf(elementData, newCapacity);
    
    即底层会创建一个新的长度为10的数组,证毕
    
    当for循环执行完毕结束,此时,list.size=10,我们再次向集合中添加一个元素,同样调用add方法,
    
    有add---------->ensureCapacityInternal---------->ensureExplicitCapacity(calculateCapacity(elementData, minCapacity))---------->grow(minCapacity)
    
    只不过在grow(minCapacity)方法中minCapacity=size+1=11
    
    int oldCapacity = elementData.length;  10
    
    newCapacity = oldCapacity + (oldCapacity >> 1); 10+5=15
    
    newCapacity - minCapacity < 0 不满足  15-11=4>0
    
    newCapacity - MAX_ARRAY_SIZE > 0 不满足 15-(Integer.MAX_VALUE - 8)<0
    
    两个if条件都不满足,继而执行elementData = Arrays.copyOf(elementData, newCapacity);
    
    此时newCapacity为15,即存满时,会扩容1.5倍,证毕
    
     */


}

posted on 2024-01-31 00:28  周政然  阅读(32)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3