千呼万唤始出来,犹抱琵琶半遮面,揭开ArrayList的扩容机制的神秘面纱
ArrayList
- ArrayList的成员变量
- 构造方法
- 添加元素
- 重现ArrayList的扩容机制
ArrayList顺序表(物理结构连续,逻辑结构连续)
用一段物理地址连续的存储单位存储数据元素的线性结构,底层是一个数组
ArrayList的成员变量
// 一个常变量,常用于表示数组容量(长度)
private static final int DEFAULT_CAPACITY = 10;
// final修饰的Object数组
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 底层数组,初始值 null
transient Object[] elementData;
// 记录数组中的元素个数
private int size;
构造方法
- 不传参数
不传参数,elemData数组初始化,指向DEFAULTCAPACITY_EMPTY_ELEMENTDATA({}
)
public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}
- 传指定容量
initialCapacity > 0 数组初始化,数组长度是initialCapacity
initialCapacity = 0 数组初始化,指向EMPTY_ELEMDATA({}
)
initialCapacity < 0 抛出异常
public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}
- 传一个Connection类元素的集合
(1). 将集合转化为数组,elemData指向这个数组
(2).集合的长度为0,elemData指向EMPTY_ELEMDATA({})
(3).集合长度不为0,此时elemData的类型也在改变,将elemData转化为Object类型
public ArrayList(Collection<? extends E> c) {elementData = c.toArray();if ((size = elementData.length) != 0) {// c.toArray might (incorrectly) not return Object[] (see 6260652)if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);} else {// replace with empty array.this.elementData = EMPTY_ELEMENTDATA;}}
添加元素
以添加一个元素为例
- 先进行扩容操作(可能不需要扩容)
- 添加元素
public boolean add(E e) {ensureCapacityInternal(size + 1); // Increments modCount!!elementData[size++] = e;return true;}
- 确定需要的数组容量(此处是 size + 1)
private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}
- 计算数组容量应该是多大
- 如果ArrayList是通过 ArrayList()无参数构造方法 构造的,并且是第一次添加元素
此时elemData指向 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
数组容量应该定为DEFAULT_CAPACITY- 其他情况,数组容量一律定位 指定的容量(size+1)
private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;}
- 判断该不该扩容
如果 经上述计算操作决定的数组容量 <= 现有数组的容量,不扩容
否则,扩容
private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0)grow(minCapacity);}
- 扩容多少呢
经过上面操作决定的数组容量(minCapacity) < 现有数组容量(oldCapacity)的3/2,新数组的容量就是 oldCapacity的3/2
如果minCapacity >= oldCapacity的3/2,新数组的容量就是minCapacity
private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1);if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:elementData = Arrays.copyOf(elementData, newCapacity);}
重现ArrayList的扩容机制
public class MyArraysList<T> {private int DEFAULT_CAPACITY = 10;private int[] EMPTY_ELEMDATA = {};private int[] DEFAULT_CAPACITY_EMPTY_ELEMDATA = {};private int[] elemData;private int size;// 构造方法public MyArraysList(){elemData = DEFAULT_CAPACITY_EMPTY_ELEMDATA;}public MyArraysList(int initialCapacity){if(initialCapacity < 0){return;}if(initialCapacity == 0){elemData = EMPTY_ELEMDATA;}elemData = new int[initialCapacity];}// 添加元素public void add(int t){ensureCapacityInternal(size + 1);elemData[size++] = t;}// 指定位置添加元素public void add(int index, int t) {if (index > size || index < 0) {throw new IndexOutOfBoundsException();}ensureCapacityInternal(size + 1);int moveLength = size - index;System.arraycopy(elemData, index, elemData, index + 1, moveLength);elemData[index] = t;size++;}// 添加一个集合public void addAll(int index, Collection<? extends T> c){if(index > size || index < 0){throw new IndexOutOfBoundsException();}Object[] newArray = c.toArray();int len = newArray.length;ensureCapacityInternal(size + len);int moveLength = size - index;System.arraycopy(elemData, index, elemData, index + len, moveLength);System.arraycopy(newArray, 0, elemData, index, len);}public void ensureCapacityInternal(int newCapacity){// 计算需要的数组容量if(elemData == DEFAULT_CAPACITY_EMPTY_ELEMDATA){newCapacity = DEFAULT_CAPACITY;}// 扩容ensureExplicitCapacity(newCapacity);}public void ensureExplicitCapacity(int newCapacity){// 需不需要扩容if(newCapacity > elemData.length){// 扩容多大int oldCapacity = elemData.length + (elemData.length >> 1);if(newCapacity < oldCapacity){newCapacity = oldCapacity;}elemData = Arrays.copyOf(elemData, newCapacity);}}@Overridepublic String toString() {return "MyArraysList{" +"elemData=" + Arrays.toString(elemData) +'}';}
}
千呼万唤始出来,犹抱琵琶半遮面,揭开ArrayList的扩容机制的神秘面纱相关推荐
- exchange揭开拨号音还原法的神秘面纱
之前exchange揭开拨号音还原法的神秘面纱英文版本的翻译,用了两周的时间翻译出来!图片感觉很小,可以下载附件直接查看,会更好! 揭开exchange拨号音恢复的方法(第一部分) 在这三部分系列里, ...
- javascript关键字_让我们揭开JavaScript的“ new”关键字的神秘面纱
javascript关键字 by Cynthia Lee 辛西娅·李(Cynthia Lee) 让我们揭开JavaScript的" new"关键字的神秘面纱 (Let's demy ...
- arraylist 的扩容机制_ArrayList详解
作者丨HUC南枫 来源丨甲哇技术栈(jiawa1024)ArrayList 的底层是数组队列,相当于动态数组.与 Java 中的数组相比,它的容量能动态增长.在添加大量元素前,应用程序可以使用ensu ...
- 轻轻揭开 b*tree 索引结构的神秘面纱
李翔宇 云和恩墨西区技术专家 大家好,我是云和恩墨的技术专家李翔宇,今天要为大家分享的主题是<轻轻揭开b*tree索引结构的神秘面纱>. 说到索引,大家应该都或多或少的了解甚至熟悉它,它是 ...
- 揭开自然拼读法(Phonics)的神秘面纱
揭开自然拼读法(Phonics)的神秘面纱 自然拼读法 (Phonics),是指看到一个单词,就可以根据英文字母在单词里的发音规律把这个单词读出来的一种方法.即从"字母发音-字母组合发音- ...
- java基础巩固-宇宙第一AiYWM:为了维持生计,多高(多线程与高并发)_Part9~整起(单双列集合们、ArrayList 的扩容机制、HashMap、ConcurrentHashMap )
再进入正文之前,先看看集合相关操作的时间复杂度: 本故事源自于~ 开唠: PART0: 为什么突然蹦出集合这个玩意,就是因为咱们基础那里学的"数组"不够用~: 数组一般用来保存一组 ...
- 80老翁谈人生(291):揭开沃森超级电脑的神秘面纱
80老翁谈人生(291):揭开沃森超级电脑的神秘面纱 当今,国外媒体掀起鼓吹IBM沃森超级电脑的狂浪,每天新闻不断.沃森超级电脑是什么"神物"?它的工作原理如何? 2016年6月, ...
- arraylist 的扩容机制_每天都用ArrayList,你读过它的源码么?
作者:陌北有棵树,玩Java,架构师社区合伙人! [一]关于扩容 如果没有指定初始容量,则设置为10 /** * Default initial capacity. */private static ...
- 说一说 ArrayList 的扩容机制
ArrayList有三种方式来初始化,构造方法源码如下: /*** 默认初始容量大小*/private static final int DEFAULT_CAPACITY = 10;private s ...
- 比MySQL快839倍!揭开分析型数据库JCHDB的神秘面纱
前不久,京东智联云云产品研发部架构师王向飞老师在线上公开课<Clickhouse在京东智联云的大规模应用和架构改良>中,介绍了Clickhouse 数据库在京东智联云的落地应用与优化改进经 ...
最新文章
- 51单片机教程哪个好?
- Tensorflow【实战Google深度学习框架】基于tensorflow + Vgg16进行图像分类识别
- kohana中的路由规则
- SNF软件开发机器人-子系统-功能-【列表】自由排序-如何配置?
- 使用java操作ranger,hdfs ranger授权操作,hive ranger授权操作
- Creator-配置MSVC调试器
- codevs1040统计单词个数(区间+划分型dp)
- c 读取mysql另一个窗体中显示出来_二级ACCESS数据库4窗体的笔试题考点分析
- P2617 Dynamic Ranking
- aws消息服务器,经验分享:我们如何使用AWS构建无服务器架构 - hypertrack
- jQuery HTML操作
- c++之二维数组参数传递
- 细说 ASP.NET控制HTTP缓存[转]
- Atitit oracle新特性5 6 7 8 9 10 11 12 18 19 20 attilax总结 目录 1.1. :ora 20c	1 1.2. Oracle Database 19c 的
- Linux基础知识点总结
- CDH Parcel包starrocks集成cloudera Manager
- 图片高斯模糊效果的实现
- mysql 安装教程(个人经验,仅供参考)
- paddle video_tag paddle.fluid.io.xmap_readers
- ValueError: With n_samples=0, test_size=0.15 and train_size=None, the resulting train set will be em