源码分析|LinkedList

1.什么是LinkedList

LinkedList是一个线性的,以双向链表形式实现的有序性的集合,由于是链表实现,因此执行添加和删除操做时效率比较高,执行查询操做时效率比较低。bash

2.LinkedList构造方法分析

public LinkedList() {
}
复制代码

当不传入参数时,会建立一个空的LinkedListui

3.add()方法

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以及后继nullNode类型的节点赋值给newNode节点,再将newNode赋给lastfirst。这就至关于cdn

最后将 size进行维护

4.addFirst()方法

list.add("aaa");
list.addFirst("hello");
复制代码

点击进入会发现blog

public void addFirst(E e) {
    linkFirst(e);
}
复制代码

再点击linkFirstelement

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,此时firstlast已经不指向相同的元素了,再将f的前驱指向newNode,随着方法的结束fnewNode也会随之失效,最终的效果会是这样。rem

5.addLast()

list.add("aaa");
list.addFirst("hello");
list.addLast("world");
复制代码

点击addLaststring

public void addLast(E e) {
    linkLast(e);
}
复制代码

再点击linkLastit

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也会消失。最终结果会是这样

6.removeFirst()

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不成立,就会将待删除元素下一个节点的前驱设置为空。最后将保存的元素返回。

7.removeLast()

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,由于前面有元素因此前驱不为空,因此会将本身的前一个元素的后继设置为空,这样就与上一个元素断开了链接,最后将保存的元素返回。

相关文章
相关标签/搜索