ArrayList源码解析
1.Arraylist()
Public Arraylist()
初始化一个空的Object[]{}数组集合
2.ArrayList(int initialCapacity)
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
1).若容器入参是否大于0,那么elementData(数组)直接初始化为入参大小
2).若容器入参=0,那么elementData(数组)直接初始化空数组{}
3).其他情况则throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity)
3.ArrayList(Collection<? extends E> c)
public ArrayList(Collection<? extends E> c) {
Object[] a = c.toArray();
if ((size = a.length) != 0) {
if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else {
// replace with empty array.
elementData = EMPTY_ELEMENTDATA;
}
}
1).通过c.toArray函数转成Object[]数组
2).将集合大小初始化为a.length,如果数组长度不等于0 则判断数组类型是否为arraylist.class类型,如果是,则将集合数组赋为入参数组
3).负责通过Arrays.copyof方式将数组内容转为Object[]数组,并赋值
4).若入参集合为空,则初始化数组为空集合
4.add(E e)
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
- 第一行 ensureCapacityInternal进行数组的扩容,size+1为了保证新数组能满足要求
- 第二行则赋值
private void ensureExplicitCapacity(int minCapacity) {
modCount++; #1
if (minCapacity - elementData.length > 0) #2
grow(minCapacity); #3
}
#1 modCount表示修改的次数
#2 判断传进来的容量是否大于当前容量
#3 如果满足第二行则进行扩容
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; #1
int newCapacity = oldCapacity + (oldCapacity >> 1); #2
if (newCapacity - minCapacity < 0) #3
newCapacity = minCapacity; #4
if (newCapacity - MAX_ARRAY_SIZE > 0) #5
newCapacity = hugeCapacity(minCapacity); #6
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity); #7
}
#1 获取原数组容量
#2 计算新数组的容量=老数组容量+老数组容量向右移一位(相当于新数组容量为老数组容量的1.5倍)
#3 老数组容量*1.5小于传入新数组的容量
#4则将新数组容量赋值为传入的容量
#5.如果新数组超过了最大数组大小(Integer.MAX_VALUE-8)
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
#6.如果大于Integer.MAX_VALUE()则数组大小设置为Integer.MAX_VALUE,否则设置为MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8)
#7.通过Arrays.copy新生一个数组返回赋值给当前数组
注:
Integer.MAX_VALUE - 8 java数组它不是类,没有对应的class文件,所以数组是由jvm从元素类型合成出来的,所以jvm需要专门的需要通过arrayleng获取所以这个8就是专门用来存储数组长度的
5.add(int index, E element)
public void add(int index, E element) {
rangeCheckForAdd(index); #1
ensureCapacityInternal(size + 1); #2 // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);#3
elementData[index] = element; #4
size++; #5
}
#1.校验下标是否已超出数组的长度
#2.如果有需要则进行扩容
#3 以传入的节点为起点,之后的节点都往后移一位
#4 赋值
#5 容量+1
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
6.set(int index, E element)
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
此方法比较简单,主要是对下标检验是否越界,指定数组位置进行赋值
7.get(int index)
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
此方法比较简单,主要是先校验下标,根据下标获取数组对应的值,得到数据后进行类型强转
8.remove(int index)
public E remove(int index) {
rangeCheck(index); #1
modCount++;
E oldValue = elementData(index); #2
int numMoved = size - index - 1; #3
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved); #4
elementData[--size] = null; #5 // clear to let GC do its work
return oldValue; #6
}
#1.校验传入的数值与数组非空数据数量进行比较,若传入的数据>=数组元素的数量则报数组索引边界异常(throw new indexOutOfBoundsException)
#2.获取index位的值
#3 计算需要移动多少位数组元素
#4 如果需要移动的位数>0则将原数组index+1位开始到numMoved位进行复制并覆盖到原index位上
#5 将元素最后一位赋值为null(去除引用,帮助虚拟机进行垃圾回收)
#6 返回被删除的元素