ArrayList的源码分析(基于jdk1.8)
1.初始化
transient Object[] elementData; //实际存储元素的数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
//初始化为一个默认的空数组
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
2. 添加元素
private static final int DEFAULT_CAPACITY = 10;//默认容量
public boolean add(E e) {
//确保当前数组的容量是够得
ensureCapacityInternal(size + 1); // Increments modCount!!
//将新元素添加到[size++]的位置
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
//如果是第一次添加
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//扩容为默认容量大小:10
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//每一次添加都要判断是否需要扩容
ensureExplicitCapacity(minCapacity);
}
3.扩容
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 如果需要扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private 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);
}
4.结论
ArrayList物理结构是数组,决定了它的存储特点是:需要开辟连续的存储空间来存储元素,当存储容量不够时,需要扩容,增加容量为原来的1.5倍。类似的,Vector的物理结构也是数组,当存储容量不够时,需要扩容为原来的2倍。那么是1.5倍好呢?还是2倍好呢?1.5倍使得数组空间使用率提高了,但是这也增加了扩容的频率。所以,建议大家在选择动态数组时,如果对要存储的元素个数有一个预估时,那么可以在创建ArrayList时,就使用ArrayList(int initialCapacity) 构造器,避免反复扩容。
ArrayList的源码分析(基于jdk1.8)的更多相关文章
- HashMap 源码分析 基于jdk1.8分析
HashMap 源码分析 基于jdk1.8分析 1:数据结构: transient Node<K,V>[] table; //这里维护了一个 Node的数组结构: 下面看看Node的数 ...
- CopyOnWriteArrayList 源码分析 基于jdk1.8
CopyOnWriteArrayList 源码分析: 1:成员属性: final transient ReentrantLock lock = new ReentrantLock(); //内部是 ...
- HashMap源码分析-基于JDK1.8
hashMap数据结构 类注释 HashMap的几个重要的字段 hash和tableSizeFor方法 HashMap的数据结构 由上图可知,HashMap的基本数据结构是数组和单向链表或红黑树. 以 ...
- ArrayList 源码分析 基于jdk1.8:
1:数据结构: transient Object[] elementData; //说明内部维护的数据结构是一个Object[] 数组 成员属性: private static final int ...
- LinkedList的源码分析(基于jdk1.8)
1.初始化 public LinkedList() { } 并未开辟任何类似于数组一样的存储空间,那么链表是如何存储元素的呢? 2.Node类型 存储到链表中的元素会被封装为一个Node类型的结点.并 ...
- ArrayList的源码分析
在项目中经常会用到list集合来存储数据,而其中ArrayList是用的最多的的一个集合,这篇博文主要简单介绍ArrayList的源码分析,基于JDK1.7: 这里主要介绍 集合 的属性,构造器,和方 ...
- AtomicInteger源码分析——基于CAS的乐观锁实现
AtomicInteger源码分析——基于CAS的乐观锁实现 1. 悲观锁与乐观锁 我们都知道,cpu是时分复用的,也就是把cpu的时间片,分配给不同的thread/process轮流执行,时间片与时 ...
- 并发-AtomicInteger源码分析—基于CAS的乐观锁实现
AtomicInteger源码分析—基于CAS的乐观锁实现 参考: http://www.importnew.com/22078.html https://www.cnblogs.com/mantu/ ...
- ArrayList迭代器源码分析
集合的遍历 Java集合框架中容器有很多种类,如下图中: 对于有索引的List集合可以通过for循环遍历集合: List<String> list = new ArrayList<& ...
随机推荐
- Linux文件系统的实现 ZZ
作者:Vamei 出处:http://www.cnblogs.com/vamei Linux文件管理从用户的层面介绍了Linux管理文件的方式.Linux有一个树状结构来组织文件.树的顶端为根目录(/ ...
- Ubuntu下安装CUDA
cuda check: cuDNN 下载cuDNN后解压 更新软链接 更新链接库 symbol link 参考链接: http://docs.nvidia.com/cuda/cuda-installa ...
- LINUX基础了解
- 从0开始学CentOS7(1)
首先,先来几句简介吧.. java开发一枚,总觉得自己的技术提升缓慢... 最近看到同事有在论坛发发自己的心得什么的...我脑中晃出的灵光就是:好记性不如烂笔头,试试吧~ 好了,正式开始了..cent ...
- Webpack笔记(一)——从这里入门Webpack
准备了挺久,一直想要好好深入了解一下Webpack,之前一直嫌弃Webpack麻烦,偏向于Parcel这种零配置的模块打包工具一些,但是实际上还是Webpack比较靠谱,并且Webpack功能更加强大 ...
- 牛客网多校训练第一场 D - Two Graphs
链接: https://www.nowcoder.com/acm/contest/139/D 题意: 两个无向简单图都有n(1≤n≤8)个顶点,图G1有m1条边,图G2有m2条边,问G2有多少个子图与 ...
- Sonar安装和常见问题解决
Sonar是一款代码质量分析工具,有助于帮助代码质量提高. Sonar的官网地址为:https://www.sonarqube.org/downloads/ 点击 Show All Versions ...
- Qgis里的查询过滤
查询过虑实现方式 通过给getFeatures()传递 QgsFeatureRequest对象,实现数据的过虑,下边是一个查询的例子: request = QgsFeatureRequest() re ...
- 转:javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 解决方案
转:javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 解决方案javax.net.ssl.SSL ...
- 用Java+xml配置方式实现Spring数据事务(编程式事务)
一.用Java配置的方式 1.实体类: Role public class Role { private int id; private String roleName; private String ...