注:玩的是JDK1.7版本
一:先上类的继承结构图
二:再看一下他的底层实现数据结构
三:然后从源码中找点好玩的东西
1)双向链表的结构构成元素,头指针、尾指针、节点信息(前向指针、后向指针、节点信息)
/*** Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)*/
transient Nodefirst;/*** Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)*/
transient Node last;
private static class Node{
E item;
Nodenext;
Nodeprev;
Node(Node prev, E element, Nodenext) {this.item =element;this.next =next;this.prev =prev;
}
}
2)在链表尾部添加新节点,只需要改变链表尾指针的指针指向就可了,所以,性能相对 ArrayList.java 的数组拷贝会好很多
/*** Appends the specified element to the end of this list.
*
*
This method is equivalent to {@link#addLast}.
*
*@parame element to be appended to this list
*@return{@codetrue} (as specified by {@linkCollection#add})*/
public booleanadd(E e) {
linkLast(e);return true;
}
/*** Links e as last element.*/
voidlinkLast(E e) {final Node l =last;final Node newNode = new Node<>(l, e, null);
last=newNode;if (l == null)
first=newNode;elsel.next=newNode;
size++;
modCount++;
}
3)根据索引位置,获取节点,会遍历链表性能相对会差一些,并且我们也能看到遍历的时候也有一个优化,通过索引位置和链表长度的一半比较,决定从头遍历还是从尾遍历,这样能通过减少遍历长度加快遍历速度的作用,不过当索引位置在中间的时候,就不好玩了,无论从头或从尾遍历性能不会比较差
/*** Returns the element at the specified position in this list.
*
*@paramindex index of the element to return
*@returnthe element at the specified position in this list
*@throwsIndexOutOfBoundsException {@inheritDoc}*/
public E get(intindex) {
checkElementIndex(index);returnnode(index).item;
}
/*** Returns the (non-null) Node at the specified element index.*/Node node(intindex) {//assert isElementIndex(index);
if (index < (size >> 1)) {
Node x =first;for (int i = 0; i < index; i++)
x=x.next;returnx;
}else{
Node x =last;for (int i = size - 1; i > index; i--)
x=x.prev;returnx;
}
}
4)根据节点信息获取索引位置的方法,可以看到节点信息是允许为null的
/*** Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index {@codei} such that
* (o==null ? get(i)==null : o.equals(get(i))),
* or -1 if there is no such index.
*
*@paramo element to search for
*@returnthe index of the first occurrence of the specified element in
* this list, or -1 if this list does not contain the element*/
public intindexOf(Object o) {int index = 0;if (o == null) {for (Node x = first; x != null; x =x.next) {if (x.item == null)returnindex;
index++;
}
}else{for (Node x = first; x != null; x =x.next) {if(o.equals(x.item))returnindex;
index++;
}
}return -1;
}
5)下面的三个方法,是根据索引位置,修改、删除索引位置的节点,都会遍历链表,所以,性能相对会差一些,ArrayListljava 是通过数组的索引位置直接操作的
/*** Replaces the element at the specified position in this list with the
* specified element.
*
*@paramindex index of the element to replace
*@paramelement element to be stored at the specified position
*@returnthe element previously at the specified position
*@throwsIndexOutOfBoundsException {@inheritDoc}*/
public E set(intindex, E element) {
checkElementIndex(index);
Node x =node(index);
E oldVal=x.item;
x.item=element;returnoldVal;
}
/*** Inserts the specified element at the specified position in this list.
* Shifts the element currently at that position (if any) and any
* subsequent elements to the right (adds one to their indices).
*
*@paramindex index at which the specified element is to be inserted
*@paramelement element to be inserted
*@throwsIndexOutOfBoundsException {@inheritDoc}*/
public void add(intindex, E element) {
checkPositionIndex(index);if (index ==size)
linkLast(element);elselinkBefore(element, node(index));
}
/*** Removes the element at the specified position in this list. Shifts any
* subsequent elements to the left (subtracts one from their indices).
* Returns the element that was removed from the list.
*
*@paramindex the index of the element to be removed
*@returnthe element previously at the specified position
*@throwsIndexOutOfBoundsException {@inheritDoc}*/
public E remove(intindex) {
checkElementIndex(index);returnunlink(node(index));
}
6)双向链表也可以当做双向队列使用