java基础源码 (6)--ArrayListt类
原作出处:https://www.cnblogs.com/leesf456/p/5308358.html
简介:
1、ArrayList是一个数组队列,相当于动态数组。与java中的数组相比,它的容量能动态增长,它继承与AbstractList,实现List,RandomAccess,Cloneable,java.io.Serizlizable这些接口
2、ArrayList继承AbstractList,实现了List,它是一个数组队列,提供了相关的增、删、改、遍历等功能
3、ArrayList实现了RandomAccess接口,即提供了随机访问功能。RandomAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。
4、ArrayList实现了Cloneable接口,即覆盖了函数clone(),能被克隆
5、ArrayList实现了java.io.Serizlizable接口,这意味着ArrayList支持序列化,能通过序列化去传输。
6、ArrayList不是线程安全的,在单线程中才使用
数据结构:参考API1.8文档 的ArrayList
java.lang.Object
java.util.AbstractCollection<E>
java.util.AbstractList<E>
java.util.ArrayList<E> All Implemented Interfaces:
Serializable , Cloneable , Iterable <E>, Collection <E>, List <E>, RandomAccess

ArrayList构造函数:参考API1.8文档 的ArrayList
ArrayList()
构造一个初始容量为十的空列表。
ArrayList(Collection<? extends E> c)
构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。
ArrayList(int initialCapacity)
构造具有指定初始容量的空列表。
ArrayList包含了两个重要的对象:
1、elementData:
elementData是“Object []类型的数组”,它保存了添加到ArrayList中的元素。实际上,elementData是个动态数组,我们能通过构造函数ArrayList(int initialCapacity)来执行它的初始容量为initialCapacity;如果通过不含参数的构造函数ArrayList()来创建ArrayList,则elementData的容量默认是10,elementData数组的大小会根据ArrayList容量的增长而动态的增长
2、size:
size则是动态数组的实际大小。
源码解析:
类属性:类属性中核心的属性为elementData,类型为Object[],用于存放实际元素,并且被标记为transient,也就意味着在序列化的时候,此字段是不会被序列化的
//序列版本号
private static final long serialVersionUID = 8683452581122892189L;
//初始容量为10
private static final int DEFAULT_CAPACITY = 10;
//空对象数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//(无参)缺省空对象数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//元素数组
transient Object[] elementData;
//实际元素大小
private int size;
//最大数组容量 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
类构造器:
//指定elementData数组大小,不允许初始化大小,小于0,否则抛异常
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {//初始容量大于0
this.elementData = new Object[initialCapacity];//根据传入initalCapacity初始化元素数组
} else if (initialCapacity == 0) {//初始容量为0
this.elementData = EMPTY_ELEMENTDATA;//将属性的空对象赋值给元素数组
} else {//小于0,抛异常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
} /**
*当为指定初始化大小时,会给elementData赋值为空集合
*/
public ArrayList() {
//将属性的无参空对象数组赋值给元素数组
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//党传递的参数为集合类型时,会把集合类型转为数组类型,并赋值给elementData
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)//是否成功转为Object类型数组
elementData = Arrays.copyOf(elementData, size, Object[].class);//不为Object数组的话就进行复制
} else {//判断参数为空,则将空对象数组赋值给元素数组
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
核心函数:
1、add:
在add函数还有ensureCapacityInternal,此函数可以理解为确保elementData数组有合适的大小。
public boolean add(E e) {//添加元素
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
1.1、ensureCapacityInternal:
在ensureCapacityInternal方法中ensureExplicitCapacity是为了确保elementData元素数组有合适的大小
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//判断元素数组是否为空
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//取较大值
}
ensureExplicitCapacity(minCapacity);
}
1.2、ensureExplicitCapacity:
grow方法才会对数组进行扩容,1.1、1.2都只是过程,最后完成实际扩容操作是grow方法
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//结构性修改+1
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
1.3、grow:
正常情况下会扩容1.5倍,特殊情况下(新扩展数组大小已达到最大值)则只取最大值
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;//元素数组大小(旧容量)
int newCapacity = oldCapacity + (oldCapacity >> 1);//新容量为旧容量的1.5倍
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);
}
2、set:设定指定下标索引的元素值
public E set(int index, E element) {
rangeCheck(index);//检验索引是否合法,否则抛异常
E oldValue = elementData(index);//旧值
elementData[index] = element;//赋新值
return oldValue;//返回旧值
}
3、indexOf:
从头开始查找与指定元素相等的元素。注意是可以查找Null元素的,意味着ArrayList中可以存放null元素的。与此对应的lastIndexOf,表示从尾部开始查找
//从首开始查找数组里面是否存在指定元素
public int indexOf(Object o) {
if (o == null) {//判断元素是否为空
for (int i = 0; i < size; i++)//遍历数组
if (elementData[i]==null)//找到第一个为空的元素
return i;//返回它的下标
} else {//元素不为空
for (int i = 0; i < size; i++)//遍历数组
if (o.equals(elementData[i]))//找到第一个和指定元素相等的元素
return i;//返回下标
}
return -1;//没有找到,返回-1
}
4、get
get方法会检查索引是否合法(只检查是否大于size,而没有检查是否小于0)
public E get(int index) {
rangeCheck(index);//检验索引是否合法
return elementData(index);
}
4.1 、elementData:
返回值都经过了向下 转型(Object(elementData元素数组是Object类型的)->E),这些是对我们应用程序屏蔽的小细节
E elementData(int index) {
return (E) elementData[index];
}
5、remove:
移除指定下标的元素,此时会把指定下标到数组末尾的元素向前移动一个单位,并且会把数组最后一个元素设置为NUll,这样是为了方便之后将这个数组不被使用时,会被GC(垃圾回收),可以做为小的技巧使用
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);
//赋值为空,有利于进行GC(垃圾回收)
elementData[--size] = null; // clear to let GC do its work
//返回旧值
return oldValue;
}
java基础源码 (6)--ArrayListt类的更多相关文章
- java基础源码 (1)--String类
这个是String类上面的注释,我用谷歌翻译翻译的,虽然有点语法上的问题,但是大概都可以翻译出来 /** * The {@code String} class represents character ...
- java基础源码 (2)--StringBuilder类
Serializable(接口): 是一个IO的序列化接口,实现了这个接口,就代表这个类可以序列化或者反序列化,该接口没有方法或者字段,仅用于标识可串行话的语义. Appendable(接口): /* ...
- java基础源码 (5)--reflect包-AccessibleObject类
学习参考博客:https://blog.csdn.net/benjaminzhang666/article/details/9664585AccessibleObject类基本作用 1.将反射的对象标 ...
- java基础源码 (3)--Annotation(注解)
借鉴博客地址:https://www.cnblogs.com/skywang12345/p/3344137.html /** * The common interface extended by al ...
- java基础源码 (4)--reflect包-AnnotatedElement接口
接口:AnnotatedElement * Represents an annotated element of the program currently running in this * VM. ...
- 自学Java HashMap源码
自学Java HashMap源码 参考:http://zhangshixi.iteye.com/blog/672697 HashMap概述 HashMap是基于哈希表的Map接口的非同步实现.此实现提 ...
- Java基础-DBCP连接池(BasicDataSource类)详解
Java基础-DBCP连接池(BasicDataSource类)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程 ...
- java集合源码分析(三):ArrayList
概述 在前文:java集合源码分析(二):List与AbstractList 和 java集合源码分析(一):Collection 与 AbstractCollection 中,我们大致了解了从 Co ...
- java集合源码分析(六):HashMap
概述 HashMap 是 Map 接口下一个线程不安全的,基于哈希表的实现类.由于他解决哈希冲突的方式是分离链表法,也就是拉链法,因此他的数据结构是数组+链表,在 JDK8 以后,当哈希冲突严重时,H ...
随机推荐
- c++拷贝构造函数(翁恺c++公开课[26-27]学习笔记)
这节课在p26.拷贝构造中讲的很清楚,建议大家耐心的去看下. 什么时候会发生拷贝构造: 对象之间的初始化赋值 使用对象作为变量进行函数传参(通常使用引用来传参从而减去不必要的拷贝构造,提高效率和代码健 ...
- JS 一次性事件问题
项目的需求就是不能重复提交 是通过click点击事件提交数据,到这里的时候想了很多办法,比如说销毁这个点击事件, 但是这个实现起来是相对比较麻烦的,后面想到了一个相对比较简单的办法 通过推荐判断 JS ...
- MyuCMS_V2.1漏洞分析
前言 在CNVD看到一个MyuCMS的一个任意文件删除漏洞.然后去搜了下这个CMS,发现官网公告显示在V2.2.3版本修复了CNVD提供的多处漏洞. 怀着好奇的心里,去CNVD搜了下这个CMS,结果发 ...
- Celeste 机制研究
0. 简介.惯例.总论 Celeste (塞莱斯特) 是一个具有优秀手感的平台跳跃游戏. 虽然操作所使用的按键很少, 但是却有着复杂的组合机制. 在游戏实现上, Celeste 是一个锁定 60 帧 ...
- 在linux命令行无界面下,使用selenium进行自动化测试
- 设计模式课程 设计模式精讲 13-2 享元模式coding
1 代码演练 1.1 代码演练1 1 代码演练 1.1 代码演练1 需求: 每周由随机部门经历做报告: 重点关注: a 该案例是单例模式和享元模式共同使用 b 外部传入的department是外部状态 ...
- Python 全国考级二级
第1章 Python概述 [Python语言简介] Python是一种跨平台.开源.免费的解释型高级动态编程语言,是一种通用编程语言. Python支持命令式编程和函数式编程两种方式,并且完全支持面 ...
- Tomcat的部署、虚拟主机及优化
Tomcat的部署.虚拟主机及优化 文章目录 Tomcat的部署.虚拟主机及优化 前言 1.Tomcat的名称由来 2.Apache Tomcat 5-7版本差异 2.1Apache Tomcat5. ...
- Java编程打开运行exe程序
String path = "notepad.exe"; //(C:\Program Files\Tencent\QQ\Bin\qq.exe) try { Runtime runt ...
- 三 Spring对于延迟加载问题的解决
Spring提供了延迟加载问题的解决方法 什么是延迟加载? 延迟加载:lazy(懒加载) 执行到该行代码的时候不会发送语句,真正使用这个对象的属性的时候才会发送sql语句进行查询. 类级别延迟加载:指 ...