文章目录
- Java简单集合
- ArrayList
- 继承体系
- 源码解析
- 总结
大家好哈,欢迎来到令狐小哥本期专栏,这期专栏主要是带着大家阅读JDK源码,我会分几期篇幅来介绍这个jdk源码、会进行剖析、梳理,欢迎大家指正阅读。后面我会配套自己的视频进行讲解~
Java简单集合
ArrayList
ArrayList是一种以数组实现的List,与数组相比,它具有动态扩展的能力,因此又被称为:动态数组。
继承体系
ArrayList
实现了List
,Serializable
,RandomAccess
,Cloneable
。
ArrayList
实现了List
,提供了基础的添加,删除,遍历等操作。ArrayList
实现了Serializable
,表示可以被序列化。ArrayList
实现了Cloneable
,可以被克隆。ArrayList
实现了RandomAccess
,提供了随机访问的能力。
源码解析
/*** @Description: 源码阅读:Codelinghu* @param null* @return:* @Author: codelinghu* @Date: 2024/6/4*/public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{private static final long serialVersionUID = 8683452581122892189L;/*** ArrayList默认的容量为10* default_capacity*/private static final int DEFAULT_CAPACITY = 10;/*** 空数组,如果传入的容量为0的时候使用,* 当new ArrayList(0)的时候使用它** empty_elementdata*/private static final Object[] EMPTY_ELEMENTDATA = {};/**当new ArrayList()的时候使用它,使用这个空数组defaultcapacity_empty_elementdata*/private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};/**存储元素的数组*/transient Object[] elementData; // non-private to simplify nested class access/***集合中元素的个数*/private int size;public ArrayList(int initialCapacity) {if (initialCapacity > 0) {//如果初始化容量大于0,新建一个数组存储元素this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {//如果初始化容量等于0,使用空数组EMPTY_ELEMENTDATAthis.elementData = EMPTY_ELEMENTDATA;} else {//如果初始化容量小于0,抛出异常throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}/*** 无参构造,new ArrayList()的情况*/public ArrayList() {//如果不传初始容量,初始化为DEFAULTCAPACITY_EMPTY_ELEMENTDATA空数组,会在添加//第一个元素的时候扩容为默认的大小,10.this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}/**这个构造器会传入一个集合C,这里会使用传入集合的元素拷贝到elementData数组中*/public ArrayList(Collection<? extends E> c) {elementData = c.toArray();if ((size = elementData.length) != 0) {// c.toArray might (incorrectly) not return Object[] (see 6260652)/**如果elementData的类型不是Object[],则使用Arrays.copyOf()方法将elementData复制到一个新的Object[]类型的数组中。这样做的目的是确保elementData的类型是Object[],避免类型不匹配的问题。* @Author: codelinghu* @Date: 2024/6/4*/if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);// elementData复制到一个新的Object[]类型的数组中。这样做的目的是确保elementData的类型是Object[],避免类型不匹配的问题。} else {// 传入元素个数为0的时候replace with empty array.this.elementData = EMPTY_ELEMENTDATA;}}public void ensureCapacity(int minCapacity) {int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)// any size if not default element table? 0// larger than default for default empty table. It's already// supposed to be at default size.: DEFAULT_CAPACITY;if (minCapacity > minExpand) {ensureExplicitCapacity(minCapacity);}}//计算最小容量private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//最小也得为10,避免容量过小导致频繁扩容return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;}//检查是否需要扩容private void ensureCapacityInternal(int minCapacity) {//首先调用calculateCapacity(elementData, minCapacity)最小容量//然后调用ensureExplicitCapacity()进行扩容~ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}//传递最小容量过来,进行扩容~private void ensureExplicitCapacity(int minCapacity) {/**首先将modCount加1,表示数组结构发生了变化。然后判断minCapacity - elementData.length > 0,如果为真,说明需要扩容,调用grow(minCapacity)方法进行扩容。*/modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0)//目前数组需要的容量大于当前的容量大小grow(minCapacity);//说明需要扩容}/*** The maximum size of array to allocate.* Some VMs reserve some header words in an array.* Attempts to allocate larger arrays may result in* OutOfMemoryError: Requested array size exceeds VM limit*/private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;/**数组扩容方法growminCapacity为需要的容量*/private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;//新容量为旧容量的1.5倍int newCapacity = oldCapacity + (oldCapacity >> 1);//如果新容量小于需要的容量,则以需要的容量为准!if (newCapacity - minCapacity < 0)newCapacity = minCapacity;//如果新容量超过了最大的容量,则使用最大的容量if (newCapacity - MAX_ARRAY_SIZE > 0)//hugeCapacity(minCapacity)方法用于计算ArrayList的最大容量newCapacity = hugeCapacity(minCapacity);// 以新容量拷贝出一个新数组/**将原数组(elementData)的内容复制到一个新数组中,并确保新数组的容量(newCapacity)足够容纳更多的元素。这样,当向ArrayList添加更多元素时,就不需要频繁地进行扩容操作,* @Author: codelinghu* @Date: 2024/6/5*/elementData = Arrays.copyOf(elementData, newCapacity);}//计算ArrayList的最大容量private static int hugeCapacity(int minCapacity) {if (minCapacity < 0) // overflowthrow new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;}/*** Returns the element at the specified position in this list.*获取指定元素位置的元素*/public E get(int index) {//检查是否越界rangeCheck(index);//返回指定元素return elementData(index);}
}
总结
ArrayList
内部使用的是数组存储元素,当数组长度不够进行扩容的时候,每次加一半的空间,ArrayList
不会进行缩容。ArrayList
支持随机访问,通过索引访问元素极快、删除元素极快,但是删除中间元素比较慢,添加元素到中间也比较慢。ArrayList
支持求并集、交集、单向差集。