一、ArrayList源码分析
(一)ArrayList初始化的时候容量为0
(1)初始化ArrayList
//创建集合
ArrayList arrayList = new ArrayList();
上面的代码是进行ArrayList的初始化,然后我们进入到ArrayList的构造方法中。
(2)无参数的构造方法
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
然后我们到
DEFAULTCAPACITY_EMPTY_ELEMENTDATA 这个数组。
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
可以看出 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是定义了一个空数组。
所以,当我们初始化ArrayList的时候,ArrayList的初始化容量为空数组。
(二)ArrayList的Add方法
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
(1)我们点击 ensureCapacityInternal 方法,elementData存放元素的数组 ,size实际元素的个数,size为0。
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
因为 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 为空数组,当开始的时候,elementData 等于DEFAULTCAPACITY_EMPTY_ELEMENTDATA,这个条件成立,所以走到了,if里面,然后
DEFAULT_CAPACITY 和 minCapacity 进行对比,谁最大赋值给 minCapacity ,因为我们要添加第一个元素,所以一定是 DEFAULT_CAPACITY 这个最大,所以当我们添加第一个元素的时候,集合的容量变成了10.
当if条件走完之后,我们来到了 ensureExplicitCapacity(minCapacity);
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
现在minCapacity为10,所以if条件是成立的,
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
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);
}
elementData刚开始是没有的,所以 oldCapacity为0,int newCapacity = oldCapacity + (oldCapacity >> 1); 此时newCapacity为 0,0-10成立,所以newCaoacity= 10,所以elementData为10.
注意:oldCapacity >> 1 的意思是右移動1位,还是0.相当于除2
扩容:
int newCapacity = oldCapacity + (oldCapacity >> 1);
如果没有向集合中添加任何元素时,容量0,添加一个元素之后,容量10,每次扩容大小为原来的1.5倍。
二、LinkedList源码分析
(1)存储结构
LinkedList的存储结构为双向链表,size为大小,first指向第一个元素,last指向最后一个元素。
transient int size = 0;
/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first;
/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node<E> last;
/**
* Constructs an empty list.
*/
public LinkedList() {
}
(2)add方法
/**
* Appends the specified element to the end of this list.
*
* <p>This method is equivalent to {@link #addLast}.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
linkLast(e);
return true;
}
/**
* Links e as last element.
*/
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
此时,我们点击Node。
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
当添加第一个元素的时候,元素的类型为Node,fast指向就不为空了,是一个结点,这个结点是item是实际数据,next为下一个结点,prev为前一个结点。
/**
* Links e as last element.
*/
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
我们再看linkLast,l是Prev,null为last
执行
final Node<E> newNode = new Node<>(l, e, null);
当执行last = newNode; 这句代码
当执行到 if (l == null) , first = newNode;
当添加第二个元素执行的时候, final Node<E> newNode = new Node<>(l, e, null);
此时last还是指向e1的,当我们执行到last=newcode,就变成了last指向e2了,
当我们再执行l.next=newNode的时候