ArrayList 扩容规则[通俗易懂]

ArrayList 扩容规则[通俗易懂]ArrayList()会使用长度为零的数组ArrayList(intinitialCapacity)会使用指定容量的数组publicArrayList(Collection<?extendsE>c)会使用c的大小作为数组容量add(Objecto)首次扩容为10,再次扩容为上次容量的1.5倍addAll(Collectionc)没有元素时,扩容为Math.max(10,实际元素个数),有元素时为Math.max(原容量1.5倍,实际元素个数.

大家好,又见面了,我是你们的朋友全栈君。

1. ArrayList() 会使用长度为零的数组

如果是无参构造,则会将DEFAULTCAPACITY_EMPTY_ELEMENTDATA(空对象)的值复制给elementData, 再执行添加操作时,才会给数组赋值(见第四点)
在这里插入图片描述
DEFAULTCAPACITY_EMPTY_ELEMENTDATA空对象
在这里插入图片描述
追踪add方法可到这儿

//1 . add(E e)
 public boolean add(E e) { 
   
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
   //2.ensureCapacityInternal
   private void ensureCapacityInternal(int minCapacity) { 
   
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    //3.calculateCapacity
 private static int calculateCapacity(Object[] elementData, int minCapacity) { 
   
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 
   
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

2. ArrayList(int initialCapacity) 会使用指定容量的数组

在这里插入图片描述

3. public ArrayList(Collection<? extends E> c) 会使用 c 的大小作为数组容量

在这里插入图片描述

4. add(Object o) 首次扩容为 10,再次扩容为上次容量的 1.5 倍

在这里插入图片描述在这里插入图片描述// private static final int DEFAULT_CAPACITY = 10;
在这里插入图片描述
// 如果是扩容,则扩容老数据组的1.5倍
在这里插入图片描述
在这里插入图片描述

5. addAll(Collection c) 没有元素时,扩容为 Math.max(10, 实际元素个数),有元素时为 Math.max(原容量 1.5 倍, 实际元素个数)

在这里插入图片描述

后面主要还是扩容这一段代码:

注: 有元素时为什么为 是Math.max(原容量 1.5 倍, 实际元素个数),主要是这里可能发生一次扩容,如果原数组长度+新添加的c的长度大于原容量,则会扩容一次成为原容量的1.5倍;如果原数组长度+新添加的c的长度不超过原容量,则不会扩容

  private static int calculateCapacity(Object[] elementData, int minCapacity) { 
   
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 
   
            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);
    }
    ```

测试代码:
···java
public class ArrayListAddCapacity { 
   

    public static void main(String[] args) { 
   
      // System.out.println(arrayListGrowRule(30));
       // testAddAllGrowEmpty();
        testAddAllGrowNotEmpty();
    }

    /** * 空构造方法 * @param n * @return */
    private static List<Integer> arrayListGrowRule(int n) { 
   
        List<Integer> list = new ArrayList<>();
        int init = 0;
        list.add(init);
        if (n >= 1) { 
   
            init = 10;
            list.add(init);
        }
        for (int i = 1; i < n; i++) { 
   
            init += (init) >> 1;
            list.add(init);
        }
        return list;
    }

    /** * addAll(Collection c) 没有元素时 */
    private static void testAddAllGrowEmpty() { 
   
        ArrayList<Integer> list = new ArrayList<>();
        list.addAll(Arrays.asList(1, 2, 3));
        list.addAll(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
        System.out.println(length(list));
    }

    /** * addAll(Collection c) 有元素时 */
    private static void testAddAllGrowNotEmpty() { 
   
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < 1; i++) { 
   
            list.add(i);
        }
        list.addAll(Arrays.asList(1, 2, 3));
        System.out.println(length(list));
        list.addAll(Arrays.asList(1, 2, 3, 4, 5, 6, 7));
        System.out.println(length(list));
    }
	/** 反射获取数组长度 */
    public static int length(ArrayList<Integer> list) { 
   
        try { 
   
            Field field = ArrayList.class.getDeclaredField("elementData");
            field.setAccessible(true);
            return ((Object[]) field.get(list)).length;
        } catch (Exception e) { 
   
            e.printStackTrace();
            return 0;
        }
    }

}

来源: https://www.bilibili.com/video/BV15b4y117RJ?p=32

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/136818.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • SCL语言(入门初级笔记)「建议收藏」

    SCL语言(入门初级笔记)「建议收藏」点动控制电机程序//点动陈序IF”点动启动”=1THEN”KM1点动”:=1;ELSE”KM1点动”:=0;END_IF;

  • hbase列表排序

    hbase列表排序

    2021年12月17日
  • tomcat打印日志乱码,入库数据正常_tomcat输出日志乱码

    tomcat打印日志乱码,入库数据正常_tomcat输出日志乱码Tomcat后台日志乱码问题文章目录Tomcat后台日志乱码问题一、找到乱码原因二、Tomcat端乱码处理三、IDEA端设置小结一、找到乱码原因  基本上我们安装的windows系统本地语言都是中文,用的是GBK编码,而我们IDEA和Tomcat日志选择的是utf8编码,因此编码方式不一致造成了我们的中文乱码问题。二、Tomcat端乱码处理  既然原因已经找到了,接着就是解决问题了,分别设置IDEA和Tomcat的编码就ok了。先对Tomcat进行处理,如下:  1.找到Tomcat的安装目录

  • 有关于微信公众号网页开发的流程(自己的看法)

    有关于微信公众号网页开发的流程(自己的看法)微信官方文档(真的很详细)第一步:网页授权回调域名网页服务内容这个网页回调域名是非常关键的,后面会讲解这个回调的域名的使用,回调字面意思就是会跳转的。第二步:使用微信官方的api进行code获取这个就是获取code进行页面跳转,给跳转的页面传递code参数,你可以在自己的页面进行获取,将code传给后端参考链接(请在微信客户端中打开此链接体验):scope为sns…

  • android studio与eclipse_androidstudio源码网

    android studio与eclipse_androidstudio源码网 以前公司的老项目,是使用eclipse进行开发的,虽然androidstudio出来了很久,但为了避免迁移会有一些问题,一直忍着没改,但最近谷歌公司上架有要求,要求android的项目要用android8.0来编译,然后就发现eclipse+ADT已经不支持jdk1.8还有android8.0,运行就会有问题,有类似unsported52.0,还有各种莫名其妙的错误,比如无法识别27,…

  • 打开名为window2_connection string

    打开名为window2_connection stringDotNetTextBox是一个很不错的在线编辑工具,我一直在用它。最近使用中发现它和window的history对象有冲突,原因就是它定义了一个全局的名为history的对象,覆盖默认的window.history。所以当你想在页面中调用“后退”功能(window.history.go(-1))时会产生脚本错误,找不到对象或方法。解决方法:在history对象变量前定义一全局变量…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号