LinkedList分析

模仿遊戲.jpeg

上次咱們分析了ArrayList,你們都已經瞭解了分析一個集合的步驟。那接下來,咱們繼續分析LinkedList。廢話不很少說,直接整。node

查看LinkedLis成員

/**
     * 指針指向第一個節點
     * 初始化: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node<E> first;

    /**
     * 指針指向最後一個節點
     * 初始化: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node<E> last;
複製代碼

從LinkedList成員中,能夠看出Lined內部有兩個指針,first(指向第一個節點)與Last(指向最後一個節點)。查看相關Node類聲明:安全

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;
        }
    }
複製代碼

Node類中,保存了當前數據元素,上一個節點,及下一個節點。從這裏,咱們大概瞭解到了LinkedList的內部結構是鏈表。bash

1、添加元素

add(e)方法

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

複製代碼

add方法內部調用了linkLast(e),繼續走linkLast(e)。ui

查看linkLast(e)方法

void linkLast(E e) {
        final Node<E> l = last;//last指向最後一個節點。
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;//frist指向第一個添加元素
        else
            l.next = newNode;//不是第一次添加,上一個節點的next指向當前節點
        size++;
        modCount++;
    }
複製代碼

當該方法執行是,會初始化一個Node節點保存當前添加元素及上一個節點。若是是第一次執行,該方法,first與Last都會指向該節點。若是不是第一次執行。上個節點的next會指向新添加的節點,且last指向新添加的節點。this

addFist(e)方法

addFist(e)中方法直接調用了linkFrist(e)方法,咱們直接查看LinkFirst方法:spa

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方法內部建立了一個新的節點。若是是第一次添加。新節點上個節點爲null。若是不是,則新的節點的上個的節點爲first原來指向的節點,first指向新添加的節點。線程

addLast(e)方法原理與addFirst(e)原理差很少,這裏就直接跳過了

2、獲取元素

get(Index)方法

public E get(int index) {
        checkElementIndex(index);//判斷是否操做存儲的長度
        return node(index).item;
    }
複製代碼

get方法先判斷時候在有效範圍類,若是調用了node(index)方法返回相應元素,繼續走node方法。3d

Node<E> node(int index) {
        // assert isElementIndex(index);
        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

複製代碼

該方法內部先判斷index的位置是否小於總長度的一半,若是是,則從鏈表前方遍歷,若是不是,則從鏈表最末尾進行遍歷。指針

3、刪除元素

removeFirst()方法

final Node<E> f = first;
        if (f == null)//若是first沒有指向元素,拋出異常
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }
複製代碼

removeFirst()方法,先判斷當前frist時候爲null,若是不是,將first做爲參數傳入unLinkFirst()方法,查看unLinkFirst方法。code

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方法將器node中數據置爲null,且將frist節點,指向f的下一個節點。並將f的下一個節點的上個節點(也就是f)至爲null。

removeLast()方法

public E removeLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return unlinkLast(l);
    }
複製代碼

removeLast方法內把Last指向的節點,傳入unLikeLast()方法,繼續走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;
    }
複製代碼

unLinkLast方法內部獲取last重寫指向Last原節點的上一個節點,同時將Last原節點至爲null.

總結

  • LinkedList方法內部實現是鏈表,且內部有fist與last指針控制數據的增長與刪除等操做
  • LinkedList內部元素是能夠重複,且有序的。由於是按照鏈表進行存儲元素的。
  • LinkedList線程是非線程安全的,由於其內部添加、刪除、等操做,沒有進行同步操做。
  • LinkedList增刪元素速度較快。

最後,附上我寫的一個基於Kotlin 仿開眼的項目SimpleEyes(ps: 其實在我以前,已經有不少小朋友開始仿這款應用了,可是我以爲要作就作好。因此個人項目和其餘的人應該不一樣,不單單是簡單的一個應用。可是,可是。可是。重要的話說三遍。還在開發階段,不要打我),歡迎你們follow和start

相關文章
相關標籤/搜索