ArrayList
前言
Resizable-array implementation of the <tt>List</tt> interface.
* Implements
* all optional list operations, and permits all elements, including
* <tt>null</tt>.
允许null值。* In addition to implementing the <tt>List</tt> interface,
* this class provides methods to manipulate the size of the array that is
* used internally to store the list
除了实现List接口外,这个类还提供了操作内部array大小的方法。* <p>Each <tt>ArrayList</tt> instance has a <i>capacity</i>. The capacity is
* the size of the array used to store the elements in the list. It is always
* at least as large as the list size. As elements are added to an ArrayList,
* its capacity grows automatically. The details of the growth policy are not
* specified beyond the fact that adding an element has constant amortized
* time cost.
每一个ArrayList都有一个容量。容量就是ArrayList内用于存储element的array。这个大小至少要够用。* <p><strong>Note that this implementation is not synchronized.</strong>
* If multiple threads access an <tt>ArrayList</tt> instance concurrently,
* and at least one of the threads modifies the list structurally, it
* <i>must</i> be synchronized externally. (A structural modification is
* any operation that adds or deletes one or more elements, or explicitly
* resizes the backing array; merely setting the value of an element is not
* a structural modification.) This is typically accomplished by
* synchronizing on some object that naturally encapsulates the list.
*
* If no such object exists, the list should be "wrapped" using the
* {@link Collections#synchronizedList Collections.synchronizedList}
* method.
使用一个能在Synchronized的对象保持同步。或者使用Collections的synchronizedList方法进行包装。
继承类&实现接口
继承AbstractList,这个类其实就是简单实现了一些公有的方法,给所有List的实现提供了一个Skeleton。
实现了List、RandomAccess、Cloneable和Serializable接口。
RandomAccess也是一个空的接口,作用也是语义层面的。
* Marker interface used by <tt>List</tt> implementations to indicate that
* they support fast (generally constant time) random access.
构造方法
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
无参构造方法,直接初始化为DEFAULTCAPACITY_EMPTY_ELEMENTDATA。也就是说默认大小为0.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);
}
}
指定初始化大小的构造方法,要注意这里是可以把大小指定为0的,这个时候初始化为EMPTY_ELEMENTDATA。
静态变量&静态方法
private static final int DEFAULT_CAPACITY = 10;
如果使用无参构造方法初始化对象,在第一次add的时候,会开空间到DEFAULT_CAPACITY。private static final Object[] EMPTY_ELEMENTDATA = {};
Shared empty array instance used for empty instances.
如果是空的实例,且Capacity还是0的话,共享这个引用。private static final Object[] 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.
如果使用无参数的构造方法,就是共享这个的引用,这个和EMPTY_ELEMENTDATA的区别在于当加入第一个element的时候,我们知道要把容量扩充为多大。
成员变量&成员方法
transient Object[] elementData;
真正用来存储数据的数组。ArrayList并没有使用专门的变量去记录Capacity,elementData的length就是Capacity。private int size;
数组的实际大小。public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
去除多余的空间。public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
* <p>The returned array will be "safe" in that no references to it are
* maintained by this list. (In other words, this method must allocate
* a new array). The caller is thus free to modify the returned array.
返回的数组是一个全新的数组,不需要担心被list保留引用。public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
调用是Arrays的sort方法。
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
另外需要注意一下Iterator的next方法,前面提到有一个概念叫做fail-fast,第一行的checkForComodification方法就是为了fail-fast用的,如果监测到modCount不是所希望的数值,就会抛出ConcurrentModificationException异常。modCount是一个当修改或删除list内元素的时候会修改的变量。
LinkedList
前言
* Doubly-linked list implementation of the {@code List} and {@code Deque}
* interfaces.
是一个双向链表。* Implements all optional list operations, and permits all
* elements (including {@code null}).
允许插入null元素。* <p>All of the operations perform as could be expected for a doubly-linked
* list. Operations that index into the list will traverse the list from
* the beginning or the end, whichever is closer to the specified index.* <p><strong>Note that this implementation is not synchronized.</strong>
* If multiple threads access a linked list concurrently, and at least
* one of the threads modifies the list structurally, it <i>must</i> be
* synchronized externally.
该容器不是线程安全的,需要施加额外的同步手段。
继承类&实现接口
继承AbstractSequentialList类。
这个类继承AbstractList,Sequential的语义是和链表的访问方式有关系的。
实现List<E>, Deque<E>, Cloneable, java.io.Serializable接口。
注意到实现了Deque接口,也就是说LinkedList也是双端队列的一种实现。
成员变量&成员方法
transient Node<E> first;
用来记录链表头。transient Node<E> last;
用来记录链表尾。使用一个内部静态类来表示节点。
private static class Node<E> {
E item;
LinkedList.Node<E> next;
LinkedList.Node<E> prev;Node(LinkedList.Node<E> prev, E element, LinkedList.Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}transient int size = 0;
其实主要用于操作的就是下面的四个方法。
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}/**
* 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++;
}private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}/**
* Unlinks non-null last node l.
*/
private E unlinkLast(Node<E> l) {
// assert l == last && l != null;
final E element = l.item;
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // help GC
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
}