Java集合源码之路-List分析(二)

        第一章分析的List的一种常见实现ArrayList,底层基于数组结构存储元素,这一章分析List的另一种实现,

基于链表结构的实现,也就是LinkedList.首先现分析源码,最后在比较这两者之间的差异。

1、jdk逻辑图

《Java集合源码之路-List分析(二)》

2、三个主要的成员变量:

        transient int size = 0;

        transient Node<E> first;
        transient Node<E> last;


其中Class  Node<E> 是LinkedList<E>的内部静态类,具体实现这样:

《Java集合源码之路-List分析(二)》

实际上就是一个双向链表结构。

3、LinkedList提供了两个构造器

1)无参构造器

2)入参为Collection类型的集合

  核心添加元素的代码块

   public boolean addAll(int index, Collection<? extends E> c) {
        checkPositionIndex(index);     /**检查添加索引是否合法**/

        Object[] a = c.toArray();
        int numNew = a.length;
        if (numNew == 0)
            return false;

        Node<E> pred, succ;
        if (index == size) {   /**追加操作**/
            succ = null;
            pred = last;
        } else {   /**插入操作**/
            succ = node(index); /**遍历返回index索引处的节点,此处用了二分法查找的技巧**/
            pred = succ.prev; 
        }

/**遍历插入或追加元素**/
        for (Object o : a) {
            @SuppressWarnings(“unchecked”) E e = (E) o;
            Node<E> newNode = new Node<>(pred, e, null); /** 新创建一个链表节点,newNode.prev->pred,newNode->next->null,newNode.item->e**/

            if (pred == null) /**链表为空**/
                first = newNode;
            else /** 追加新的链表节点**/

                pred.next = newNode;  

                pred = newNode;
        }

        if (succ == null) { /**last指向最后添加一个元素节点**/
            last = pred;
        } else {  /**维护插入索引处节点与添加节点的指向关系**/
            pred.next = succ;
            succ.prev = pred;
        }

        size += numNew;
        modCount++;  /**fast-fail机制**/
        return true;
    }

4、重要方法分析(其实不太难《Java集合源码之路-List分析(二)》)

1)添加元素

public boolean add(E e); /**添加一个元素到链表中去**/

《Java集合源码之路-List分析(二)》

 public void add(int index, E element); /**在指定索引的处添加元素**/

 public void addFirst(E e); 

 public void addLast(E e);

以上方法很简单不在分析,读者可以自己看源码。

2)删除元素

 public E remove(); /**删除头结点**/

 public E remove(int index);/**删除指定索引的元素**/

 public boolean remove(Object o);/**删除指定对象**/

就拿 public E remove(int index);做一个简单的分析吧,

public E remove(int index) {
        checkElementIndex(index);  //检查索引的合法性
        return unlink(node(index));  //移除指定的非null结点

    }


 E unlink(Node<E> x) {
        // assert x != null;
        final E element = x.item;
        final Node<E> next = x.next;
        final Node<E> prev = x.prev;

        if (prev == null) {  //如果是头结点,则将first指向第二节点

            first = next;
        } else {
            prev.next = next; //非头结点,但是中间结点,则建立删除结点的前后结点的指向关系
            x.prev = null; //置空
        }

        if (next == null) {  //尾节点
            last = prev;
        } else {
            next.prev = prev; //非尾节点,但是中间节点,则建立删除结点的前后结点的指向关系
            x.next = null;//置空
        }

        x.item = null;  //数据域置空
        size–;  //链表元素数量更新
        modCount++;
        return element;
    }








    原文作者:java集合源码分析
    原文地址: https://blog.csdn.net/angry_tiger/article/details/51037712
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞