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)
blank

相关推荐

  • springboot中使用SFTP文件上传

    springboot中使用SFTP文件上传最近在工作功能使用了sftp做文件上传下载的功能,在这里简单的记录一下,pom文件中引入相关的jar包<!–https://mvnrepository.com/artifact/com.jcraft/jsch–><dependency><groupId>com.jcraft</g…

    2022年10月19日
  • pycharm 删除项目_ios隐藏的已购项目怎么删除

    pycharm 删除项目_ios隐藏的已购项目怎么删除PyCharm彻底删除项目直接删除源文件,删不干净,会留下一些文件1、点击File,选择CloseProject2、关闭项目之后,会弹出一个选择项目的界面,点击你想要删除的项目右边的叉3、然后找到该项目所在的路径,选中该项目的文件,“Shift+Delete”(永久删除,不放入回收站)就OK了路漫漫其修远兮,吾将上下而求索。核心关键:python实战是检验学习效果的唯一…

  • 【HTML基础】CSS样式表「建议收藏」

    【HTML基础】CSS样式表「建议收藏」1.理解HTML与CSS各自的功能及配合原则;2.掌握HTML与CSS的三种组合方式。

  • Spring Boot整合RabbitMQ详细教程

    Spring Boot整合RabbitMQ详细教程1.首先我们简单了解一下消息中间件的应用场景异步处理场景说明:用户注册后,需要发注册邮件和注册短信,传统的做法有两种1.串行的方式;2.并行的方式(1)串行方式:将注册信息写入数据库后,发送注册邮件,再发送注册短信,以上三个任务全部完成后才返回给客户端。这有一个问题是,邮件,短信并不是必须的,它只是一个通知,而这种做法让客户端等待没有必要等待的东西.(2)并行方式:将注册信…

  • c语言中的offset_c语言中/和%的区别

    c语言中的offset_c语言中/和%的区别今天看libPhenom源代码,看到他们使用的JSON解析库参考的是JanssonJSON解析库。于是就去网上查了这个库,找到了官方网站:http://www.digip.org/jansson/。找了一下发现在Github上能够下载源代码,于是下载了源代码来瞅瞅。    看了一会儿发现有一块代码一直看不明白,就比如说如下的代码:json_t*json_object(void)

  • RedisClient 可视化Redis工具下载「建议收藏」

    RedisClient 可视化Redis工具下载「建议收藏」https://github.com/caoxinyu/RedisClient网站下边的文档说明中如果电脑没有JDK,则点redisclient-win32.x86.2.0.exe如果有JDK,若是64位系统则点redisclient-win32.x86_64.2.0.jar32位系统点redisclient-win32.x86.2.0.jar…

    2022年10月12日

发表回复

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

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