单列集合之LinkedList
LinkedList底层实现了双向链表和双端队列,维护了两个属性first和last,分别指向首节点和尾结点。
每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点,最终实现双向链表。
因此LinkedList的元素的添加和删除不是通过数组完成相对效率较高。可以添加任意元素(可重复),包括null且线程不安全。
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;
}
}
LinkedList源码分析
transient int size = 0;
/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first; //first属性
/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node<E> last; //last属性
//无参构造器
public LinkedList() {
}
addf方法
public boolean add(E e) {
linkLast(e); //调用linklast
return true;
}
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null); //一个新的Node,pre指向当前链表的last(反向连接),last指向null
last = newNode; //当前链表的last更新为新增的节点
if (l == null) //如果当前链表的last已经是null,证明根本一个Node都没
first = newNode; //因此first也应该指向新增节点,也就是说链表只有唯一一个节点,也就是说第一次的时候first、last、newNode其实都指向同一个节点
else
l.next = newNode; //否则就把当前的最后一个节点的next指向新增节点(正向连接)
size++;
modCount++;
}
remove方法
1.默认删除第一个节点
public E remove() {
return removeFirst(); //默认删除第一个
}
public E removeFirst() {
final Node<E> f = first; //指向first
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item; //把f节点的内容取出来
final Node<E> next = f.next; //保存f节点的next节点
f.item = null; //f节点的内容为空
f.next = null; // help GC //f节点的next也为空
first = next; //first指向第二个节点
if (next == null) //如果第二个节点是空,那么last也指向是null
last = null;
else
next.prev = null; //如果第二个节点不是null,那么其pre肯定指向null,因为刚刚那个节点被删除了
size--;
modCount++;
return element; //返回f节点的值,让你知道删除了什么
}