写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站。博主很喜欢的一句话
花开堪折直须折,莫待无花空折枝
:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事,做自己以后不会留有遗憾的事,做自己觉得有意义的事,不浪费这大好的青春年华。博主写博客目的是记录所学到的知识并方便自己复习,在记录知识的同时获得部分浏览量,得到更多人的认可,满足小小的成就感,同时在写博客的途中结交更多志同道合的朋友,让自己在技术的路上并不孤单。
目录:
1.ArrayList概述
2.成员变量的源码解析(JDK1.8)
3.构造方法的源码解析(JDK1.8)
4.内部类源码解析(JDK1.8)
5.add()方法源码解析(JDK1.8)
6.数组扩容原理源码解析(JDK1.8)
7.大数据插入问题
8.remove()方法源码解析(JDK1.8)
9.get()方法源码解析(JDK1.8)
10.set()方法源码解析(JDK1.8)
11.indexOf()方法源码解析(JDK1.8)
12.contains()方法源码解析(JDK1.8)
13.toArray()方法源码解析(JDK1.8)
14.ArrayList集合的三种遍历方式
15.ArrayList和数组之间的转换
16.多线程场景下使用ArrayList
17.ArrayList的优缺点
1.ArrayList概述
1.1.ArrayList简介
java.util.ArrayList
集合数据存储的结构是数组结构(它的底层原理其实就是一个Object数组)。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合。
1.2.ArrayList特点:
1.它是基于数组实现的List类
2.可以动态地调整容量
3.有序的(元素输出顺序与输入顺序一致)
4.元素可以为 null
5.不同步,非线程安全,效率高
6.查询快,增删慢
7.用空间更小,对比 LinkedList,不用占用额外空间维护链表结构
2.成员变量的源码解析
// 序列号
private static final long serialVersionUID = 8683452581122892189L;
// 数组初始容量为 10
private static final int DEFAULT_CAPACITY = 10;0
// 空对象数组
private static final Object[] EMPTY_ELEMENTDATA = {
};
// 缺省空对象数组,如果使用默认构造方法创建对象内容是该值
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
};
// 底层数据结构,数组,当前对象存放的地方,当前对象不参与序列化
transient Object[] elementData;
// 当前数组元素个数,默认为0
private int size;
// 最大数组容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
注意看ArrayList 的 elementData 加上 transient 修饰可以这么解释:
再看一下 ArrayList 的定义:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
可以看到 ArrayList 实现了 Serializable 接口,这意味着 ArrayList 支持序列化。transient 的作用是说不希望 elementData 数组被序列化,重写了 writeObject 实现:
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{
*// Write out element count, and any hidden stuff*
int expectedModCount = modCount;
s.defaultWriteObject();
*// Write out array length*
s.writeInt(elementData.length);
*// Write out all elements in the proper order.*
for (int i=0; i<size; i++)
s.writeObject(elementData[i]);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
每次序列化时,先调用 defaultWriteObject() 方法序列化 ArrayList 中的非 transient 元素,然后遍历 elementData,只序列化已存入的元素,这样既加快了序列化的速度,又减小了序列化之后的文件大小。
3.构造方法的源码解析
//默认构造方法,初始为空数组。
//只有插入一条数据后才会扩展为10,而实际上默认是空的
public ArrayList() {
// 把空的对象数组赋给elementData
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//根据指定容量创建对象数组
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
//创建initialCapacity大小的数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
//创建空数组
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
* 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。
*/
public ArrayList(Collection<? extends E> c) {
//转换最主要的是toArray(),这在Collection中就定义了
elementData = c.toArray();//toArray返回一个数组
if ((size = elementData.length) != 0) {
// c.toArray 有可能不返回一个 Object 数组
if (elementData.getClass() != Object[].class)//因为所有的Object数组共用一个Class文件
//使用 Arrays.copy 方法拷创建一个 Object 数组
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// 替换为空数组
this.elementData = EMPTY_ELEMENTDATA;
}
}
为了理解所有的Object数组共用一个Class文件,我们随机创建两个Object数组:
package untl;
public class MyObject {
public static void main(String[] args) {
Object arr []=new Object[10];
Object brr []=new Object[20];
if(arr.getClass()==brr.getClass())
{
System.out.println("所有的Object数组共用一个Class文件");
}
else
System.out.println("不同的Object数组不一定共用一个Class文件");
}
}
运行结果:
所有的Object数组共用一个Class文件
4.内部类源码解析
(1)private class Itr implements Iterator<E>
(2)private class ListItr extends Itr implements ListIterator<E>
(3)private