LinkedList源码分析
1 初始化
LinkedList也实现了List接口,说明了也具备了插入和删除功能,基于链表,插入和删除比ArrayList快,但是随机访问能力差,这个基础数据结构已经说明了,不再重复。其次LinkedList具备了双端队列的功能,实现了Deque接口
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
}
基本字段如下:
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() {
}
主要是通过两个节点来操作链表的,first节点和last节点。size用来存储当前节点的大小。
2 插入数据
LinkedList 可以往链表前面和链表后面插入数据,这样也具备了双端队列的功能
public void addFirst(E e) {
linkFirst(e);
}
/**
* Appends the specified element to the end of this list.
*
* <p>This method is equivalent to {@link #add}.
*
* @param e the element to add
*/
public void addLast(E e) {
linkLast(e);
}
下面两个方法演示了往链表的前和后插入节点,基本都很简单,跟书上数据结构的方式一样
private void linkFirst(E e) {
//节点f指向first节点
final Node<E> f = first;
//新建一个节点
final Node<E> newNode = new Node<>(null, e, f);
//first指向新节点
first = newNode;
//如果f节点是null,那么就把last节点指向新节点,
//如果不是null那么f节点的prev节点指向了新节点
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++;
}
3 随机访问数据
下面代码是LinkedList随机访问节点的流程,这里做了个优化,查找的时候不是全部遍历节点,而是判断了下index的位置是上半部分还是下半部分。从这里可以看出来,链表的随机访问效率低下的地方,因为需要遍历节点,而不是跟顺序表一样,可以通过下标进行访问
Node<E> node(int index) {
// assert isElementIndex(index);
//判断index是否小于size的50%,如果是那么从first节点开始遍历,否则从last开始遍历
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;
}
}
4 删除数据
//删除节点这里逻辑也非常清晰,跟普通的链表操作一致,从链表头部开始删除。
public E remove() {
return removeFirst();
}
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
//拿到f节点的对象
final E element = f.item;
//拿到f节点的下一个节点
final Node<E> next = f.next;
//置为空
f.item = null;
f.next = null; // help GC
把first节点置为next节点
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}