static final int DEFAULT_CAPACITY = 10;
static final Object[] EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;
private Object[] grow() {
return grow(size + 1); //传进数组元素个数+1的数量
}
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
//假如数组长度不为空,使用ArraySupport.newLength方法扩容为原来的1.5倍
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
//数组长度右移1位,也就是除以2
return elementData = Arrays.copyOf(elementData, newCapacity);
//将元素复制到原数组长度1.5倍的新数组
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
//假如原数组长度为0,则初始化新的长度为10的数组
}
}
===================================================================================== //ArraySupport中的newLength方法:
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
// assert oldLength >= 0
// assert minGrowth > 0
//oldLength为原数组长度,minGrowth为size+1减去原数组长度,preGrowth为原数组长度除以2
int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
//比较minGrowth与preGrowth的大小,这里得到preGrowth较大,用preGrowth加上原数组长度,也就是用原数组长度×1.5
if (newLength - MAX_ARRAY_LENGTH <= 0) {
return newLength;
}
return hugeLength(oldLength, minGrowth);
}
有参构造:构造具有指定初始容量(即参数)的空列表
public ArrayList(int initialCapacity) { //initialCapacity为自定义初始容量
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity]; //初始值大于0,则创建该容量大小的数组elementData
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA; //初始值等于0,创建空的数组elementData
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
} //初始值小于0,报错
}
空参构造:构造一个初始容量为10的空列表
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
ArrayList考虑到节省内存,仅仅是创建了ArrayList对象,初始化了一个空数组,在首次添加元素时,才真正初始化容量为10的数组
在空参构造中,使用的是DEFAULTCAPACITY_EMPTY_ELEMENTDATA;空数组,而不是EMPTY_ELEMENTDATA,因为DEFAULTCAPACITY_EMPTY_ELEMENTDATA首次扩容为10,而EMPTY_ELEMENTDATA是按照1.5倍扩容从0开始而不是10
查询指定元素出现的的索引:
int indexOfRange(Object o, int start, int end) {
Object[] es = elementData; //将对象数组赋值给es数组
if (o == null) {
for (int i = start; i < end; i++) {
if (es[i] == null) {
return i;
}
} //如果传进的元素为null,经过遍历数组返回Null的索引
} else {
for (int i = start; i < end; i++) {
if (o.equals(es[i])) {
return i;
}
} //如果传进的元素不为null,遍历数组找到该元素返回索引
}
return -1;
}
============================================================================================
public int indexOf(Object o) {
return indexOfRange(o, 0, size);
} //计算索引的方法调用indexOfRange()方法,传进要查询的元素,并且从0开始,最多到数组中包含的元素个数
add()方法:
public boolean add(E e) {
modCount++; //增加修改次数
add(e, elementData, size); //添加元素
return true;
}
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow(); //如果容量不够进行扩容
elementData[s] = e; //数组扩容后,将元素个数作为下标,s-1是最后一个元素的索引,那么s就是要添加的元素所在的索引位置,所以将该位置赋值为e
size = s + 1; //元素个数+1
}
public void add(int index, E element) {
rangeCheckForAdd(index); //检查Index是否越界
modCount++; //增加修改次数
final int s;
Object[] elementData;
if ((s = size) == (elementData = this.elementData).length)
elementData = grow(); //如果数组大小不够进行扩容
System.arraycopy(elementData, index,
elementData, index + 1,
s - index);
//从数组中的index位置开始,将index及index之后的元素复制进同一个数组中的index+1的位置,也就是从index开始,所有之后的元素都往后挪了一位,空出了index位置
elementData[index] = element; //将index赋值为新元素
size = s + 1;
}
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
//将指定源数组中的数组从指定位置复制到目标数组的指定位置。
src :源数组、 srcPos:源数组中的起始位置、 dest:目标数组、 destPos:目标数组的起始位置、 length:要复制的数组元素的数目
addAll()方法
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray(); //将集合转变为数组
modCount++;
int numNew = a.length;
if (numNew == 0)
return false;
Object[] elementData;
final int s;
if (numNew > (elementData = this.elementData).length - (s = size))
elementData = grow(s + numNew);
//如果将要添加的新集合的元素数量大于原集合的空位置,则将原数组进行扩容。扩容的大小必须至少能装下新集合
System.arraycopy(a, 0, elementData, s, numNew);
size = s + numNew;
return true;
}
contains方法:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
//计算要查询元素的索引,当索引值>=0时,返回true
集合转数组:toArray()方法:
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
//调用Arrays工具类的复制方法,传进对象数组复制为一个新数组,新数组的长度为原数组的元素个数size
get()方法:
public E get(int index) {
Objects.checkIndex(index, size); //检查传入的参数index,是否在0到size范围内
return elementData(index); //返回对象数组中索引为index的元素
}
set()方法:
public E set(int index, E element) {
Objects.checkIndex(index, size); //检查传入的参数index,是否在0到size范围内
E oldValue = elementData(index); //旧值为数组对象中索引为index的值
elementData[index] = element; //将传入的新值传入数组中index索引的位置
return oldValue; //返回旧值
}
remove()方法:
public E remove(int index) {
Objects.checkIndex(index, size); //检测 index 是否越界
final Object[] es = elementData;
//记录该索引的原值
@SuppressWarnings("unchecked") E oldValue = (E) es[index];
fastRemove(es, index); //快速移除
return oldValue;
}
=====================================================================================
private void fastRemove(Object[] es, int i) {
modCount++; //增加修改次数
//如果i不是最末尾的元素,则将i+1位置的数组往前挪
final int newSize;
if ((newSize = size - 1) > i) //size-1的原因是:size是从1开始数,而索引下标从0开始
System.arraycopy(es, i + 1, es, i, newSize - i);
//将新的末尾元素变为null
es[size = newSize] = null;
}
public boolean remove(Object o) {
final Object[] es = elementData;
final int size = this.size;
//找首个元素为O的位置
int i = 0;
found: {
if (o == null) { //如果o为Null
for (; i < size; i++) //遍历数组
if (es[i] == null)
break found;
} else {
for (; i < size; i++)
if (o.equals(es[i]))
break found;
}
return false; //如果没找到返回false
}
fastRemove(es, i); //快速移除
return true; //找到了返回true
}
hashCode()方法:
public int hashCode() {
//得到当前数组的修改次数
int expectedModCount = modCount;
//计算哈希值
int hash = hashCodeRange(0, size);
//如果修改次数发生变化,则抛出ConcurrentModificationException异常
checkForComodification(expectedModCount);
return hash;
}
int hashCodeRange(int from, int to) {
final Object[] es = elementData;
//如果元素个数超过数组长度,抛出ConcurrentModificationException异常
if (to > es.length) {
throw new ConcurrentModificationException();
}
//遍历每一个元素 *31求哈希值
int hashCode = 1;
for (int i = from; i < to; i++) {
Object e = es[i];
hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
}
return hashCode;
}
clear()方法:
public void clear() {
modCount++;
final Object[] es = elementData;
for (int to = size, i = size = 0; i < to; i++)
es[i] = null;
//先将数组元素个数清零,再将每一个索引位置赋值为null
}
equals方法:
public boolean equals(Object o) {
//如果元素就是本身,返回true相等
if (o == this) {
return true;
}
//如果不为List类型 直接返回false不相等
if (!(o instanceof List)) {
return false;
}
boolean equal = root.equalsRange((List<?>)o, offset, offset + size);
checkForComodification(); //检测modCount是否被更改过,如果被更改贼抛出并发修改异常
return equal;
}
boolean equalsRange(List<?> other, int from, int to) {
final Object[] es = elementData;
if (to > es.length) {
throw new ConcurrentModificationException();
//如果to 大于 es的大小,这说明发生了改变,抛出并发修改异常
}
//通过迭代器遍历 other 然后逐个进行比对
var oit = other.iterator();
for (; from < to; from++) {
//如果 oit没有下一个,或者元素不相等,返回false不匹配
if (!oit.hasNext() || !Objects.equals(es[from], oit.next())) {
return false;
}
}
//通过检测oit是否遍历完成判断大小是否相等
return !oit.hasNext();
}
//Objects的equals方法:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
原文:https://www.cnblogs.com/rxz110010/p/15135214.html