LinkedList是一个线性的,以双向链表形式实现的有序性的集合,由于是链表实现,因此执行添加和删除操做时效率比较高,执行查询操做时效率比较低。bash
public LinkedList() {
}
复制代码
当不传入参数时,会建立一个空的LinkedListui
list.add("aaa");
复制代码
当第一次调用add()
方法时,点击add()
显示以下内容spa
public boolean add(E e) {
linkLast(e);
return true;
}
复制代码
在添加方法的内部会调用linkLast
方法,再点进去code
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<E> l = last
,其中last是transient Node<E> last;
,下一个语句是包含前驱l
和元素自己e
以及后继null
的Node
类型的节点赋值给newNode
节点,再将newNode
赋给last
及first
。这就至关于cdn
size
进行维护
list.add("aaa");
list.addFirst("hello");
复制代码
点击进入会发现blog
public void addFirst(E e) {
linkFirst(e);
}
复制代码
再点击linkFirst
element
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++;
}
复制代码
先是将transient Node<E> first;
赋值给f
,由于前面添加了元素aaa
,因此f
会指向aaa
节点。再将前驱为null
元素值为e
后继为f
的节点Node
赋值给newNode
,再将newNode
赋值给first
,此时first
和last
已经不指向相同的元素了,再将f
的前驱指向newNode
,随着方法的结束f
和newNode
也会随之失效,最终的效果会是这样。rem
list.add("aaa");
list.addFirst("hello");
list.addLast("world");
复制代码
点击addLast
string
public void addLast(E e) {
linkLast(e);
}
复制代码
再点击linkLast
it
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++;
}
复制代码
先将last
赋值给l
,再将前驱为l
元素值为e
后继为null
的节点赋值给newNode
,这时newNode
为最后一个元素并将本身与前一个元素相连,由于前面已经添加了两个元素因此l==null
不成立,因此会将l
的后继指向newNode
,随着方法的结束l和newNode
也会消失。最终结果会是这样
list.add("aaa");
list.addFirst("hello");
list.addLast("world");
list.removeFirst();
复制代码
点击removeFirst
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
复制代码
首先会将first
保存在节点f
中,再点击unlinkFirst
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;
}
复制代码
先会将节点f
的元素值和f
的后继保存,再将元素自己和后继设置为null
,由于前面添加了三个元素,因此next==null
不成立,就会将待删除元素下一个节点的前驱设置为空。最后将保存的元素返回。
list.add("aaa");
list.addFirst("hello");
list.addLast("world");
list.removeFirst();
list.removeLast();
复制代码
点击removeLast
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
复制代码
先将last
节点保存,点击unlinkLast
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;
}
复制代码
将节点的元素值和元素的前驱进行保存,再将节点自己和前驱设置为null
,由于前面有元素因此前驱不为空,因此会将本身的前一个元素的后继设置为空,这样就与上一个元素断开了链接,最后将保存的元素返回。