目录
ArrayList底层是采用数组
ArrayList构造函数
并未开辟空间,将elementData设置为空{ }
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
ArrayList add分析
初次add 会将开辟一个长度为10的数组,之后每次添加,size+1为需要的容量,如果需要的容量>数组现在的长度
则数组需要再次扩容,按1.5倍扩容
比如:从add 1到add15中,add 1时候数组开辟,之后add 2到10时候
需要的容量<=数组长度10,此期间都不需要扩容,当add 11时,需要的容量11>数组长度10,此时数组扩容到15,
当add 12..15时,均不需扩容,add 16是再次按照1.5倍扩容...........
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
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);//初始容量为10,DEFAULT_CAPACITY,返回10
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {//参数为需要的最小容量
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)//如果需要的容量>数组实际容量则需要扩容
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);//1.5倍扩容
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);
}
ArrayList Get分析
public E get(int index) {
rangeCheck(index);
return elementData(index);//直接返回
}
ArrayList 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);//从数组中index+1位置开始移动numMoved个到
//数组中index开始的位置
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
LinkedList底层是链表
LinkedList构造函数
public LinkedList() {//什么也没干
}
LinkedList add分析
初次add新节点,将新节点设置为头节点和尾节点,再次add,则将新节点链接到链表最后(尾节点后面)
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) { final Node<E> l = last;//获取到最后一个元素,
final Node<E> newNode = new Node<>(l, e, null); last = newNode;//新节点作为尾节点
if (l == null)//如果没添加前的尾节点是null,代表链表还没有元素,则尾节点也是头结点
first = newNode;
else //如果没添加前的尾节点不是null,则把添加前的尾节点的后面链上新的尾节点
l.next = newNode; size++; modCount++;
}
LinkedList Remove分析
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));//通过node(index)寻找到要删除的节点
}
*/
E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev;
if (prev == null) {//删除的是头结点
first = next;
} else {//不是头结点,就将上一个节点链接上要删除的节点的next节点
prev.next = next;
x.prev = null;
}
if (next == null) {//删除的节点是尾节点
last = prev;
} else {//不是尾节点,则将next节点的前指针指向要删除的节点的prev
next.prev = prev;
x.next = null;
}
x.item = null;
size--;
modCount++;
return element;
}
LinkedList Get分析
此时的index并非是真正意义上的下标,而是放入链表中的顺序,序号 get(4) 代表获取放入链表中的第4个元素
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
Node<E> node(int index) {//如果index是链表总长度的一半多,则从尾部开始寻找,不够一半则从头结点开始寻找,一直到index位置取出
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}