java集合LinkedList的底层实现源码详解

LinkedList类继承了AbstractSequentialList

实现了List,Deque,Cloneable,java.io.Serializable接口

1.LinkedList中的三个属性size,first,last,都用了transient关键字,首先解释一下这个关键字,因为实现了Serializable接口这个对象就会被序列化了,会将对象的持久化的保存在硬盘上,可以把堆内存中中的对象的生命周期延长,存入硬盘,当下次遇到这个对象就不用重新创建,可以直接在内存中使用了,会将对象存储到.object的文件里。而transient就是

为了解决对象中有些属性不需要序列化,就使用transient关键字,就会使这个属性的生命周期仅存在于调用者内存中而不会持久化到磁盘中。

size是int类型

first是Node类型(第一个结点)

 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;
        }
    }

属于双向链表,每一个结点封装了三个属性,前驱结点,当前元素,后继结点。

同理last属性

2.LinkedList有两个构造器

第一个构造器可以得到一个空的List

 public LinkedList() {
 }
第二个构造

 public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }
这个构造器会存放指定集合的元素的List集合,并且会返回一个集合的迭代器

3.LinkedList的方法

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++;
    }
linkFirst方法将e作为第一个元素保存到集合中,还有一个linkLast的方法,与此方法同理,将当前元素作为集合中的最后一个元素

void linkBefore(E e,Node<E> succ){
      final Node<E> pred=succ.prev;
      final Node<E> newNode=new Node<>(pred,e,succ);
      succ.prev=newNode;
      if(pred==null)
            first=newNode;
      else
            pred.next=newNode;
      size++;
      modCount++;
}

linkBefore方法是将当前元素插入到succ元素之前,首先得到当前元素的前驱结点,然后构造出新结点,将新结点赋给succ结点的前驱,但是如果succ为第一个结点,那么新结点就会成为当前的第一个结点。

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;
    }

unlinkFirst()删除一个非空的first结点,如果next==null;说明已经是最后一个结点了,若不是则正常删除,同理则有删除一个非空的last结点和一个非空结点的方法unlinkLast()和unlink()方法,则不详细介绍,其原理都是一致的,我们只需要掌握它的逻辑。

 public E getFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return f.item;
}

getFirst()方法,是得到List集合中的第一个元素值,还有类似的getLast()方法。

 public boolean contains(Object o) {
        return indexOf(o) != -1;
 }
contains()方法判断List集合中是否包含o结点,并且调用了indexOf()方法。

public int indexOf(Object o) {
        int index = 0;
        if (o == null) {
            for (Node<E> x = first; x != null; x = x.next) {
                if (x.item == null)
                    return index;
                index++;
            }
        } else {
            for (Node<E> x = first; x != null; x = x.next) {
                if (o.equals(x.item))
                    return index;
                index++;
            }
        }
        return -1;
}

indexOf()方法获取结点的下标位置,若不存在该元素则返回-1。

LinkedList的底层实现就是双向链表,所以LinkedList的增删的效率高。

自己一边阅读,一边做出自己的分析和见解,欢迎大家批评指正。









猜你喜欢

转载自blog.csdn.net/ai_wenkeyan/article/details/77898643