• ArrayList底层结构和源码分析


    ArrayList中维护了一个Object类型的数组elementData: 

     trainsient Object[] elementData

    其中trainsient的意思就是瞬间的,短暂的,不会被序列化

    当创建ArrayList对象时,如果使用的是无参构造器,则初始化elementData的容量为0,第一次添加时,扩容elementData为10,如需再次扩容,则扩容为原来的1.5倍

    如果使用的是指定elementData容量大小参数的构造器,则初始容器大小为指定大小,如需再次扩容,则变为原来的1.5倍

    底层源码分析(以无参构造器为例):

    进入ArrayList的无参构造器:

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

    再进入DEFAULTCAPACITY_EMPTY_ELEMENTDATA看一下:
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    发现DEFAULTCAPACITY_EMPTY_ELEMENTDATA其实就是一个空数组。

    list.add()方法调用时的底层源码分析:

    1. public boolean add(E e) {
    2. ensureCapacityInternal(size + 1); // Increments modCount!!
    3. elementData[size++] = e;
    4. return true;
    5. }

    可以看出: ensureCapacityInternal(size + 1); 先确认一下容量是否够用,

                     elementData[size++] = e;然后在添加元素

    进入 ensureCapacityInternal源码:

    可以看出,会确定minCapacity,第一次为10

    再进入到ensureExplicitCapacity源码:

    1. private void ensureExplicitCapacity(int minCapacity) {
    2. modCount++;
    3. // overflow-conscious code
    4. if (minCapacity - elementData.length > 0)
    5. grow(minCapacity);
    6. }

    其中modCount++:用来记录当前集合被修改的次数,放置多个线程同时修改这个集合

     if (minCapacity - elementData.length > 0)
                grow(minCapacity);

    这个if判断语句的意思就是如果当前容量比应该有的最小容量要小,就说明该扩容了,这个时候执行grow方法才是真正的扩容

    进入grow源码:

    1. private void grow(int minCapacity) {
    2. // overflow-conscious code
    3. int oldCapacity = elementData.length;
    4. int newCapacity = oldCapacity + (oldCapacity >> 1);
    5. if (newCapacity - minCapacity < 0)
    6. newCapacity = minCapacity;
    7. if (newCapacity - MAX_ARRAY_SIZE > 0)
    8. newCapacity = hugeCapacity(minCapacity);
    9. // minCapacity is usually close to size, so this is a win:
    10. elementData = Arrays.copyOf(elementData, newCapacity);
    11. }

     int oldCapacity = elementData.length;
     int newCapacity = oldCapacity + (oldCapacity >> 1);

    oldCapacity >> 1就是除以2的意思,int newCapacity = oldCapacity + (oldCapacity >> 1)就是说newCapacity的大小是oldCapacity的1.5倍

    即:第一次newCapacity=10,第二次及以后按照1.5倍扩容,扩容使用的方法是Arrays.copyOf,可以保证原来就有的数据不被覆盖。

     

  • 相关阅读:
    浅理解java中的泛型
    HTML 布局
    docker启动链接sqlservr的镜像时报SSl错误
    sqlmap 执行后打开其它程序
    河南开放大学与电大搜题微信公众号:携手共进,助力学习之路
    ROG STRIX GS-AX5400 使用笔记
    多线程的学习中篇下
    编程之路:蓝桥杯备赛指南
    在IDEA中如何使用tomcat部署项目
    谈谈行情与就业吧!
  • 原文地址:https://blog.csdn.net/qq_55278081/article/details/126360589