描述
ArrayList 现实了List接口,是一个顺序容器,存放元素的顺序和取出元素的顺序是一样的,内部是用<mark style="box-sizing: border-box;">数组</mark>来实现的,<mark style="box-sizing: border-box;">可以存放null</mark>
成员属性
private static final int DEFAULT_CAPACITY = 10; //默认容器长度
private static final Object[] EMPTY_ELEMENTDATA = {}; //空数组,也就是new ArrayList(0)
image.pngprivate static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //也是空数组 new ArrayList()
[图片上传失败...(image-f94dc8-1632339423811)]
transient Object[] elementData; //真正的用来保存元素的数组
private int size; //元素个数
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //可以分配的最大元素个数
protected transient int modCount = 0; //被这个list内容被修改的次数,比如add,remove() 都会加+1,这个参数也是Fail-Fast机制时使用的,通过记录modCount参数来实现。在面对并发的修改时,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险
方法
add()
image.png private void ensureCapacityInternal(int minCapacity) {
//这个if 只是在new ArrayList() 之后 add()就会进去
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//默认 10 和1 比,当然是10
}
ensureExplicitCapacity(minCapacity);//进去
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; //发送修改 modCount+1
// overflow-conscious code
if (minCapacity - elementData.length > 0) // minCapacity 是否大于原来的容器长度,这个是关键判断
grow(minCapacity); //扩容全靠它了了,哈哈
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //保存原容器的长度
int newCapacity = oldCapacity + (oldCapacity >> 1); //新的容器长度 = 原容器的长度 + 原容器的长度的一半
if (newCapacity - minCapacity < 0) //新的容器长度是否小于传进来的长度
newCapacity = minCapacity; //新的容器长度 = 传进来的长度
if (newCapacity - MAX_ARRAY_SIZE > 0) //新的容器长度大于 Integer.MAX_VALUE - 8 ?
newCapacity = hugeCapacity(minCapacity); //大于则是Integer.MAX_VALUE
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity); //进行数组拷贝,yes yes yes
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
set()
public E set(int index, E element) {
rangeCheck(index); //判断是否越界
E oldValue = elementData(index); //保存旧值用于返回
elementData[index] = element; //设置指定位置的指定值
return oldValue; //返回旧值
}
private void rangeCheck(int index) {
if (index >= size) // index >=size 就抛异常
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
get()
public E get(int index) {
rangeCheck(index); //判断是否越界
return elementData(index); //取出指定位置的值
}
private void rangeCheck(int index) {
if (index >= size) // index >=size 就抛异常
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
remove()
public E remove(int index) {
rangeCheck(index); //判断index 是否越界
modCount++; //修改次数 + 1
E oldValue = elementData(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 //用于gc回收
return oldValue; //返回旧值
}
private void rangeCheck(int index) {
if (index >= size) // index >=size 就抛异常
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
image.png
trimToSize()
public void trimToSize() {
modCount++; //修改次数 + 1
if (size < elementData.length) { //元素个数是否小于于数组的容量
elementData = (size == 0) // 元素个数==0
? EMPTY_ELEMENTDATA //赋值空数组
: Arrays.copyOf(elementData, size);//否则拷贝一个元素个数长度的数组
}
}
indexOf() 记得是用对象的equals来判断的
public int indexOf(Object o) {
if (o == null) { //因为可以存null 所以需要判断是否是个null
for (int i = 0; i < size; i++)
if (elementData[i]==null) //是null 返回
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i])) //equals
return i;
}
return -1;
}
网友评论