ArrayList类中的属性
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
@java.io.Serial
private static final long serialVersionUID = 8683452581122892189L;
/**
* DEFAULT_CAPACITY表示集合默认的初始容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 空数组EMPTY_ELEMENTDATA,在使用有参构造方法时传递0进去,创建ArrayList集合时就会使用这个数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
默认容量的空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 集合中真实存储元素的数组elementData
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* 集合中元素的个数
* @serial
*/
private int size; //int类型的成员变量初始值为0
ArrayList类中的构造方法
无参构造方法
使用无参构造方法创建ArrayList集合时,默认初始化容量为 0
当第一次调用add方法添加元素时ArrayList的容量初始化为 10
public ArrayList() {
//将成员变量中的 默认容量的空数组 赋值给 真实存储元素的数组
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
无参构造方法创建的对象:添加方法
第一次添加数据:
在main方法中:
package test;
import java.util.ArrayList;
import java.util.List;
public class ArrayListTest1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
//第一次添加元素
list.add("zhangsan");
}
}
第一次向集合中添加数据的流程:
-
一级一级的调用下去
public boolean add(E e) {
modCount++; //记录对当前集合操作的次数
add(e, elementData, size); //size为集合中元素的个数
return true;
}
--------------------------------------------
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length) //如果集合的size == elementData数组的长度,就扩容
elementData = grow(); //返回新的数组并赋值给elementData
//将要添加的元素 添加 到数组中有数据的下一个位置
elementData[s] = e;
size = s + 1; // size = 0 + 1
}
-------------------------------------------------------------
private Object[] grow() {
return grow(minCapacity:size + 1); //需要的最小容量:0 + 1
}
----------------------------------------------------------------
//minCapacity:是ArrayList集合需要的最小容量
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length; //获取数组的原容量 0
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
结论:第一次添加元素时,会扩容为10
第二次添加数据:
-
第二次添加元素也还不会扩容
main方法中:
package test;
import java.util.ArrayList;
import java.util.List;
public class ArrayListTest1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
//第一次添加元素
list.add("zhangsan");
//第二次添加元素
list.add("lisi");
}
}
第二次添加元素的执行流程:
public boolean add(E e) {
modCount++;
add(e, elementData, size); //size是集合的长度,现在size=1
return true;
}
----------------------------------------------------------
private void add(E e, Object[] elementData, int s) { //s=1
if (s == elementData.length) // 1 != 10 没存满,不执行
elementData = grow();
elementData[s] = e;
size = s + 1;
}
第十一次添加数据:
ArrayList集合的扩容策略:此时ArrayList集合内部的数组不够存储新元素了,会扩容为原来的1.5倍
main方法中:
package test;
import java.util.ArrayList;
import java.util.List;
public class ArrayListTest1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
//第一次添加元素
list.add("zhangsan");
//第二次添加元素
list.add("lisi");
list.add("lisi");
list.add("lisi");
list.add("lisi");
list.add("lisi");
list.add("lisi");
list.add("lisi");
list.add("lisi");
list.add("lisi");
//第十一次添加元素
list.add("lisi");
}
}
第十一次添加元素的流程:
public boolean add(E e) {
modCount++;
add(e, elementData, size); //此时size = 10
return true;
}
----------------------------------------------
private void add(E e, Object[] elementData, int s) { //s=10
//当集合中元素个数等于数组长度时会扩容 10 == 10
if (s == elementData.length)
elementData = grow(); //扩容
elementData[s] = e;
size = s + 1;
}
--------------------------------------------------------
private Object[] grow() {
return grow(size + 1); 10 + 1 = 11
}
--------------------------------------------------------------
private Object[] grow(int minCapacity) { //此时minCapacity=11
int oldCapacity = elementData.length; //获取原容量的长度 oldCapacity=10
// oldCapacity > 0 :执行
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//计算新容量:新容量newCapacity是在原容量的基础上扩容1.5倍
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth 11-10=1 */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
-----------------------------------------------------------------
// 10 最小增长:1 预期增长:5
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
//新的容量newCapacity是在原容量的基础上扩容1.5倍
//prefLength = 10 + 5 1 5
int prefLength = oldLength + Math.max(minGrowth, prefGrowth);
if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
return prefLength; //return 15
} else {
// put code cold in a separate method
return hugeLength(oldLength, minGrowth);
}
}
--------------------------------------------------------------------------
//回去继续执行grow(int minCapacity)方法
private Object[] grow(int minCapacity) { //此时minCapacity=11
int oldCapacity = elementData.length; //获取原容量的长度 oldCapacity=10
// oldCapacity > 0 :执行
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//新的容量newCapacity是在原容量的基础上扩容1.5倍
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth 11-10=1 */
oldCapacity >> 1 /* preferred growth */);
//将原数组复制到长度为15的新数组中,并将新数组复制给elementData
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
-----------------------------------------------------------
//回去grow()方法
private Object[] grow() {
return grow(size + 1);
}
-------------------------------------------------------------
//回去添加元素
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
--------------------------------------------------------
//返回
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
有参构造方法
main方法:
public class Test {
public static void main(String[] args) {
ArrayList list = new ArrayList(20); //创建一个指定初始容量为20的ArrayList集合
}
}
有参构造方法源码:
内部创建了一个指定长度的数组 并赋值给了elementData
//给定初始化容量initialCapacity
public ArrayList(int initialCapacity) { //initialCapacity=20
if (initialCapacity > 0) {
//内部创建了一个长度为20的数组,并赋值给this.elementData
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
//如果传递的是0,就将空数组EMPTY_ELEMENTDATA 赋值给 this.elementData
this.elementData = EMPTY_ELEMENTDATA;
} else {
//如果在构造方法中传递负数,就会抛出如下异常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
有参构造方法创建的对象:添加方法
执行时调用的方法都和无参的一样
main方法:
package test;
import java.util.ArrayList;
import java.util.List;
public class ArrayListTest1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(20);
list.add("lisi");
}
}
执行流程:
public boolean add(E e) {
modCount++; //对集合的操作次数+1
add(e, elementData, size); //size=0
return true;
}
-------------------------------------------------
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length) //判断内部的数组满没满,满了就扩容
elementData = grow();
elementData[s] = e;
size = s + 1;
}
ArrayList中的set方法
main方法:
package test;
import java.util.ArrayList;
import java.util.List;
public class ArrayListTest1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("lisi");
list.set(0,"李四");
}
}
源码:
public E set(int index, E element) {
Objects.checkIndex(index, size); //检查下标是否越界
E oldValue = elementData(index); //将index位置的元素取出来并保存
elementData[index] = element; //将修改后的元素存到index位置
return oldValue; //返回修改前的数据
}
ArrayList集合的插入
main方法:
package test;
import java.util.ArrayList;
public class ArrayListTest1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("lisi");
list.add("lisi");
list.add("lisi");
list.add(0,"zhangsan");
}
}
插入方法的源码执行分析:
public void add(int index, E element) { //index:0,element:"zhangsan"
rangeCheckForAdd(index); //检查下标
modCount++; //对集合的修改次数加+1
final int s;
Object[] elementData;
//集合中的元素个数 等于 数组的长度时,才会扩容
// 3 != 10
if ((s = size) == (elementData = this.elementData).length)
elementData = grow();
//从elementData数组的index下标开始拷贝,拷贝到elementData数组中,从下一个位置开始放元素
//将插入位置之后的元素都后移一位,包括插入位置的元素(通过数组的复制实现)
System.arraycopy(elementData, index, //index=0
elementData, index + 1,
s - index); //拷贝多长 3-0=3个元素
elementData[index] = element; //将元素赋值给数组元素
size = s + 1; //个数+1
}
ArrayLsit集合的remove((int index)方法
main方法:
package test;
import java.util.ArrayList;
public class ArrayListTest1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("lisi");
list.add("lisi");
list.add("lisi");
list.add(0,"zhangsan");
list.remove(0);
}
}
源码执行分析:
public E remove(int index) { index:0
Objects.checkIndex(index, size); //检查索引是否越界 index:0 size:4
final Object[] es = elementData; //将elementData数组赋值给es
@SuppressWarnings("unchecked") E oldValue = (E) es[index];
fastRemove(es, index); index:0
return oldValue;
}
------------------------------------------------------------------------
private void fastRemove(Object[] es, int i) { //i:0
modCount++;
final int newSize;
//删除一个元素,所以集合长度-1,并赋值给newSize
if ((newSize = size - 1) > i) //newSize:3 > 0
//将es数组中删除元素之后的元素都前移一个位置(通过数组的拷贝来实现)
System.arraycopy(es, i + 1, es, i, newSize - i);
//
es[size = newSize] = null; //将最后一个位置置null
}
Vector集合
main方法:
package test;
import java.util.List;
import java.util.Vector;
//Vector中所有的方法都使用了synchronized修饰,所有的方法都是线程安全的
//Vector的效率较低,已经很少使用,现在保证线程安全有了新手段
public class VectorTest1 {
public static void main(String[] args) {
//创建Vector集合
//分析源码,看看初始化容量是多少
List<String> list = new Vector<>();
//分析源码,看Vector集合是怎么扩容的
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
list.add("7");
list.add("8");
list.add("9");
list.add("10");
list.add("11"); //扩容
}
}
Vector集合的无参构造方法:
初始化容量为10
public Vector() {
this(10); //调用重载的有参构造方法,并传入10
}
-------------------------------------------------
public Vector(int initialCapacity) { initialCapacity:10
this(initialCapacity, 0); //继续调用重载的有参构造方法
}
-----------------------------------------------------------------
// 10 0
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0) 10 > 0 不执行
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//开辟一个长度为10的Object类型的数组并赋值给elementData数组
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
Vector集合扩容
源码执行流程:
Vector集合的扩容策略:每次扩容原来的2倍
public synchronized boolean add(E e) {
modCount++;
add(e, elementData, elementCount);
return true;
}
----------------------------------------------------------
"11" 10
private void add(E e, Object[] elementData, int s) {
//如果不够存入元素就扩容
if (s == elementData.length) //10 == 10
elementData = grow();
elementData[s] = e;
elementCount = s + 1;
}
-----------------------------------------------------------
private Object[] grow() {
//elementCount集合中的元素个数
return grow(elementCount + 1); //10 + 1
}
--------------------------------------------------------------
private Object[] grow(int minCapacity) { //minCapacity:10
int oldCapacity = elementData.length; //获取数组的原容量:10
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
capacityIncrement > 0 ? capacityIncrement : oldCapacity //capacityIncrement:0
/* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
}
---------------------------------------------------------
回去继续执行添加逻辑
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
elementCount = s + 1;
}
public synchronized boolean add(E e) {
modCount++;
add(e, elementData, elementCount);
return true;
}
.