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<& ...
随机推荐
- C++ virtual inheritance ZZ
虚继承 是面向对象编程中的一种技术,是指一个指定的基类,在继承体系结构中,将其成员数据实例共享给也从这个基类型直接或间接派生的其它类. 举例来说:假如类A和类B各自从类X派生(非虚继承且假设类X ...
- SVN常用功能介绍(二)
说明 上一章节主要描述了SVN的简介.安装搭建,和项目管理人员对SVN的常用操作. 这章主要讲解,SVN对应角色组员,在实际运用中的常用操作. 将SVN服务器项目导入到开发组员的本地电脑里 方式一: ...
- JAVA环境变量安装
需配置的系统环境变量参数: JAVA_HOME:C:\Program Files\Java\jdk1.8.0_60 CLASS_PATH: ;%JAVA_HOME%\lib;%JAVA_HOME%\l ...
- 【jQuery】jQuery中的事件捕获与事件冒泡
在介绍之前,先说一下JavaScript中的事件流概念.事件流描述的是从页面中接受事件的顺序. 一.事件冒泡( Event Bubbling) IE 的事件流叫做事件冒泡,即 ...
- 第三周 day3 python学习笔记
1.字符串str类型,不支持修改. 2.关于集合的学习: (1)将列表转成集合set:集合(set)是无序的,集合中不会出现重复元素--互不相同 (2)集合的操作:交集,并集.差集.对称差集.父集.子 ...
- 自动备份软件 —— Syncovery 7.98s Pro/Enterprise
SynCovery自动备份软件原名Super Flexible Synchronizer,是目前功能最为强大的实时自动备份工具,连FTP.WebDAV等全部支持!最近从V6开始改用比较好记.易懂的新名 ...
- [python]emlog相册插件getshell exploit
昨天本站转载了emlog相册插件的漏洞分析文章,当然也有html版的getshell代码,喜欢的同学们可以直接用昨天文章中分享的代码.为了练习python,小弟用python又重写了一次,喜欢的同学们 ...
- poj1322 Chocolate 【 概率DP 】
题目链接:poj1322 Chocolate [概率DP ] 题意:袋中有C种颜色巧克力,每次从其中拿出一块放桌上,如果桌上有两块相同颜色巧克力则吃掉,问取出N块巧克力后,求桌上正好剩下M块巧克力的概 ...
- Java关于日期时间的工具类
import java.sql.Timestamp; import java.text.ParseException; import java.text.ParsePosition; import j ...
- django 静态文件
django 1.8版本以上 django 静态文件配置. 小作之前, 一直觉得django的静态文件配置非常的麻烦. 1. 要设置url(r'^static/(?P<path>.*)&a ...