源码分析|LinkedList

本文由 Oo鲁毅oO 首发于 掘金,下方为原文链接
源码分析|LinkedList

1.什么是LinkedList

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

2.LinkedList构造方法分析

public LinkedList() {
}

当不传入参数时,会创建一个空的LinkedList

3.add()方法

list.add("aaa");

当第一次调用add()方法时,点击add()显示如下内容

public boolean add(E e) {
    linkLast(e);
    return true;
}

在添加方法的内部会调用linkLast方法,再点进去

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。这就相当于


最后将size进行维护

4.addFirst()方法

list.add("aaa");
list.addFirst("hello");

点击进入会发现

public void addFirst(E e) {
    linkFirst(e);
}

再点击linkFirst

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也会随之失效,最终的效果会是这样。

扫描二维码关注公众号,回复: 9376223 查看本文章

5.addLast()

list.add("aaa");
list.addFirst("hello");
list.addLast("world");

点击addLast

public void addLast(E e) {
    linkLast(e);
}

再点击linkLast

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,因为前面有元素所以前驱不为空,所以会将自己的前一个元素的后继设置为空,这样就与上一个元素断开了连接,最后将保存的元素返回。

发布了5 篇原创文章 · 获赞 0 · 访问量 52

猜你喜欢

转载自blog.csdn.net/xtxycyc/article/details/104477997