【集合框架】JDK1.8源码分析之ArrayList详解(一)
【集合框架】JDK1.8源码分析之ArrayList详解(一)
一. 从ArrayList字表面推测
ArrayList类的命名是由Array和List单词组合而成,Array的中文意思是数组,List的中文意思是列表。从ArrayList字表面推测,ArrayList类是否有数组和列表的特征?那么,这些特征这在ArrayList类中又是怎么体现的?
ArrayList源码分析
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
从上面的代码可知道,以下几点
- 继承了AbstractList类,实现了List,意味着ArrayList是一个数组队列,提供了诸如增删改查、遍历等功能。
- 实现了RandomAccess接口,意味着ArrayList提供了随机访问的功能。RandomAccess接口在Java中是用来被List实现,用 来提供快速访问功能的。在ArrayList中,即我们可以通过元素的序号快速获取元素对象。
- 实现了Cloneable接口,意味着ArrayList实现了clone()函数,能被克隆。
实现了java.io.Serializable接口,意味着ArrayList能够通过序列化进行传输。
ArrayList的属性
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;
- DEFAULT_CAPACITY :默认容量大小为10。
- EMPTY_ELEMENTDATA :用于Constructs有参数传入,如果参数等于零,则使用该属性。
- DEFAULTCAPACITY_EMPTY_ELEMENTDATA :用于Constructs无参数传入默认大小为10(具体运用于add中),使用使用该属性。
- size :当前容量大小
## 构造分析
### 有参数构造Method
传入initialCapacity参数,如果参数大于零,创建一个大小为initialCapacity的数组
/** * Constructs an empty list with the specified initial capacity. * * @param initialCapacity the initial capacity of the list * @throws IllegalArgumentException if the specified initial capacity * is negative */ public ArrayList(int initialCapacity) { if (initialCapacity > 0) { //new一个大小为initialCapacity的数组 this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
无参数构造Method
里面只有一个操作就是把 elementData
设置为 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
这个空数组。
// 无参的构造函数,传入一个空数组 这时候会创建一个大小为10的数组,具体操作在 add 中
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
增删查改Method
add Method
这个方法首先调用了 ensureCapacityInternal()
这个方法里面就判断了当前的 elementData
是否等于 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
如果是的话,就把数组的大小设置为 10 然后进行扩容操作,这里刚好解释了为什么采用无参构造的List 的大小是 10 ,这里扩容操作调用的方法是 ensureExplicitCapacity
里面就干了一件事如果用户指定的大小 大于当前长度就扩容,扩容的方法采用了 Arrays.copy
方法,这个方法实现原理是 new 出一个新的数组,然后调用 System.arraycopy
拷贝数组,最后返回新的数组。
public boolean add(E e) {
// 当调用了无参构造,设置大小为10
ensureCapacityInternal(size + 1); // Increments modCount
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
// 如果当前数组是默认空数组就设置为 10和 size+1中的最小值
// 这也就是说为什么说无参构造 new 的数组大小是 10
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 若用户指定的最小容量 > 最小扩充容量,则以用户指定的为准,否则还是 10
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 1.5倍增长
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);
}
Remove Method
通过index知道位置,然后index位置的值被index+1位置的值往前覆盖,覆盖的次数为size - index - 1
/**
* Removes the element at the specified position in this list.
* Shifts any subsequent elements to the left (subtracts one from their
* indices).
*
* @param index the index of the element to be removed
* @return the element that was removed from the list
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
get Method
通过index 来访问元素
public E get(int index) {
//检测范围
rangeCheck(index);
checkForComodification();
return ArrayList.this.elementData(offset + index);
}
set Method
通过index知道要修改的元素并替换了
public E set(int index, E e) {
rangeCheck(index);
checkForComodification();
E oldValue = ArrayList.this.elementData(offset + index);
ArrayList.this.elementData[offset + index] = e;
【集合框架】JDK1.8源码分析之ArrayList详解(一)的更多相关文章
- nginx源码分析线程池详解
nginx源码分析线程池详解 一.前言 nginx是采用多进程模型,master和worker之间主要通过pipe管道的方式进行通信,多进程的优势就在于各个进程互不影响.但是经常会有人问道,n ...
- 【集合框架】JDK1.8源码分析之ArrayList(六)
一.前言 分析了Map中主要的类之后,下面我们来分析Collection下面几种常见的类,如ArrayList.LinkedList.HashSet.TreeSet等.下面通过JDK源码来一起分析Ar ...
- vuex 源码分析(六) 辅助函数 详解
对于state.getter.mutation.action来说,如果每次使用的时候都用this.$store.state.this.$store.getter等引用,会比较麻烦,代码也重复和冗余,我 ...
- vuex 源码分析(五) action 详解
action类似于mutation,不同的是Action提交的是mutation,而不是直接变更状态,而且action里可以包含任意异步操作,每个mutation的参数1是一个对象,可以包含如下六个属 ...
- Golang源码分析之目录详解
开源项目「go home」聚焦Go语言技术栈与面试题,以协助Gopher登上更大的舞台,欢迎go home~ 导读 学习Go语言源码的第一步就是了解先了解它的目录结构,你对它的源码目录了解多少呢? 目 ...
- Java 容器源码分析之集合类详解
集合类说明及区别 Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └W ...
- Tomcat源码分析 | 一文详解生命周期机制Lifecycle
目录 什么是Lifecycle? Lifecycle方法 LifecycleBase 增加.删除和获取监听器 init() start() stop() destroy() 模板方法 总结 前言 To ...
- Cloudera Impala源码分析: SimpleScheduler调度策略详解包括作用、接口及实现等
问题导读:1.Scheduler任务中Distributed Plan.Scan Range是什么?2.Scheduler基本接口有哪些?3.QuerySchedule这个类如何理解?4.Simple ...
- 【集合框架】JDK1.8源码分析之HashMap(一) 转载
[集合框架]JDK1.8源码分析之HashMap(一) 一.前言 在分析jdk1.8后的HashMap源码时,发现网上好多分析都是基于之前的jdk,而Java8的HashMap对之前做了较大的优化 ...
随机推荐
- Windows核心编程第二章,字符串的表示以及宽窄字符的转换
目录 Windows核心编程,字符串的表示以及宽窄字符的转换 1.字符集 1.1.双字节字符集DBCS 1.2 Unicode字符集 1.3 UTF-8编码 1.4 UTF - 32编码. 1.5 U ...
- ASP .NET SignalR起步
在网站开发中,时常需要使用消息推送功能,http协议是无状态连接,我们需要一个类似桌面程序中socket保持服务器和客户端连接的技术.signalr就是这样一个技术,他能保持网站页面和服务器的一个长连 ...
- 学web前端的第一天
大家好,我是蓝颜.上次写博客是18年的4月份,不是不想写,是不知道怎么写,求写博客的技巧.从今天开始一天一更,不管写的怎么样,坚持的写下去.闲话不多说,第一次接触前端,什么都不懂,因为对这玩意的热爱, ...
- HTML 练习on方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- cesium 之地图贴地量算工具效果篇(附源码下载)
前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. 内 ...
- 图的BFS----迷宫问题
题目描述: ...11111111111111111111111111111 11.111111........1111111111.1111 11.111111..111.11111111..... ...
- #Java学习之路——基础阶段二(第二篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- Java成神之路技术整理(长期更新)
以下是Java技术栈微信公众号发布的关于 Java 的技术干货,从以下几个方面汇总. Java 基础篇 Java 集合篇 Java 多线程篇 Java JVM篇 Java 进阶篇 Java 新特性篇 ...
- 【视频】ASP.NET Core MVC 2.* 入门
比较初级的入门教程,网址在B站:https://www.bilibili.com/video/av33728783/ 内容如下: 1. ASP.NET Core 简介和开发工具 2. ASP.NET ...
- Python爬虫入门教程 42-100 爬取儿歌多多APP数据-手机APP爬虫部分
1. 儿歌多多APP简单分析 今天是手机APP数据爬取的第一篇案例博客,我找到了一个儿歌多多APP,没有加固,没有加壳,没有加密参数,对新手来说,比较友好,咱就拿它练练手,熟悉一下Fiddler和夜神 ...