方法划分成三类,初始化方法,CRUD方法,辅助方法(grow类)
CRUD方法
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
首先确保长度足够,然后赋值,这个是可以为null的。
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
首先先确保输入有效。
再确保数组长度足够
然后调用System.arraycopy方法,这个挺关键的,不要自己写,一个是重复造轮子,另外效率不如java提供的方法高。
之后赋值,size++;
clear
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
注意需要赋值null!不然只要不覆盖,GC是不work的。
get
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
注意流程,首先保证有效性,再进行操作。
indexOf
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
这要分类,对象的经典分类,为null,不为null。
remove
public E remove(int index) {
rangeCheck(index);
modCount++;
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
return oldValue;
}
源码的代码书写流程很清晰,简单地分为5步。确认有效性,主逻辑执行前置处理,执行主逻辑,主逻辑执行后处理,结果处理。
subList
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
subList不是浅拷贝,而是保留!!!
grow
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)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
首先,新的容量是原来的容量的1.5倍,如果新容量溢出,则新容量为minCapacity,如果新容量大于最大ArraySize,那么调用huge方法,在其中如果minCapacity小于0,抛出OOM。否则如果大于MAS,那么minCapacity为Integer.MAX_VALUE,否则为MAS。至此,可以创建了。
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
计算容量时,如果还没初始化过,那么得和默认容量比比,取最大值。否则直接返回,直接到ensureExplicitCapacity,这里做了两件事,一包纸minCapacity必须大于原来,二、保证不会溢出。最终调用grow函数