ArrayList的深入理解
ArrayList的源码解析
- 1. 实例化无参构造器
- 2. add()方法
- 2.1. add()List的扩容
- 3. get()方法
- 4. remove()
- 5. modCount++ 的作用(面试题)
- 5. 手写简单List实现存储删除
1. 实例化无参构造器
- Arraylist作为日常最一个类,内部是动态扩容数组,与普通数组的区别就是它是没有固定大小的限制,并且是线程不安全的
- 先看实例化的无参构造器
- 执行实例化是要调用其无参构造方法,无参构造方法就是给elementData初始化分配地址值,也就是实例化一下,不初始化的默认值为null
transient Object[] elementData; // non-private to simplify nested class access
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
2. add()方法
- 在认识一下源码中的Size,也就是数组的长度大小
- 源码中的DEFAULT_CAPACITY 也就是数组的默认值的大小
- size默认的初始化是0,调用的是ensureCapacityInternal()传递的是长度+1的数值
- 看一下方法,传递的参数是elementData,也就是list存储元素的数组和minCapacity,也就是长度+1数组的长度
- 这个判断是判断地址值是否相等,相等的话,在(默认值10,和传递的minCapacity 是数字的默认值+1),现在是返回的是10,因为10大
- modCount++; 这个操作,最后在说
- minCapacity是刚才调用的calculateCapacity方法返回的默认值和传递的大小中的最大值,目前是10
- 判断:如果10(默认长度)-elementData.length(默认值0)>0,
这个就是ArrayList中核心的一个数组扩容的方法,超过了数组的容量限制执行扩容方法
grow方法
oldCapacity 是数组原来的长度,现在是0
newCapacity是数组新的长度,用老数组位移得到
如果新数组长度-minCapacity(10初始化)=0,新的数组长度就是默认值10初始化默认值10
最后就是拷贝一份,将原elementData拷贝出来一份默认值为10的数组
- 致此,这个阶段就完成了,第一次add的ensureCapacityInternal方法的作用是初始化了一个长度为10的数组
- 然后将元素添加到数组之中返回true
2.1. add()List的扩容
- List的扩容机制体现在这里 ,第一次初始化需要扩容数组长度是10
- 然后以后每次扩容依靠的是,是够超过了数组的容量,然后进行扩容,扩容执行的是grow方法,非扩容直接添加
- 扩容扩原数组的1.5倍大小,然后copy一个新的数组,进行返回
3. get()方法
- get方法就是,传递的index超过了数组的长度就抛异常
- return elementData(index);
4. remove()
- remove方法其实就是一个拷贝的过程
第一个参数默认是src 来源数组 类型为数组
第二个参数默认是srcPos 从来源数组开始复制的位置 类型为整行(其实就是下标)
第三个参数默认是dest 目标数组 类型为数组
第四个参数默认是destPos 目标数组接收起始位置类型为整行(其实就是下标)
第五个参数默认是length 复制的长度
5. modCount++ 的作用(面试题)
- 通过看源码发现add和删除等一些地方有modCount++这个代码,这个代码的作用是,在遍历中,为了避免一边修改数据,一边拿数据,进而造成的数据混乱
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
5. 手写简单List实现存储删除
package com.rj.bd.Test;
import lombok.Data;
import java.util.Arrays;
/**
* @author LXY
* @desc
* @time 2023--04--10--10:46
*/
public class YList<T> {
//初始化
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//数组初始化默认大小
private static final int DEFAULT_CAPACITY =10;
Object[] elementData;
//初始化0
private int Size;
//添加方法
public void add(T e){
ensureCapacityInternal(Size+1);
elementData[Size++]=e;
}
public void remove(int 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
}
//添加方法
public T get(int index){
if (elementData.length-index<0){
try {
throw new Exception("数组越界");
} catch (Exception e) {
e.printStackTrace();
}
}
return (T) elementData[index];
}
//判断最大值
private int ensureCapacityMax(int minsize){
return Math.max(minsize, Size);
}
private void ensureCapacityInternal(int minsize) {
int indexs = ensureCapacityMax(minsize);
if (indexs>elementData.length){
grep(indexs);
}
}
//扩容方法
private void grep(int minCapacity) {
//原来的长度
int oldCapacity=elementData.length;
int newCapacity= oldCapacity + (oldCapacity >> 1);
if (newCapacity-minCapacity<0){
newCapacity=DEFAULT_CAPACITY;
}
elementData = Arrays.copyOf(elementData, newCapacity);
}
//无参构造器,初始化
public YList (){
elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
}