Interview Prerequisites: LinkedList source Analysis (JDK8) __java

Source: Internet
Author: User
Tags addall assert int size prev static class

Want to see more articles: "Zhang Xudong's Blog" http://blog.csdn.net/zxt0601
Want to Gayhub and me gaygayup: "Mcxtzhang GitHub Home" Https://github.com/mcxtzhang Overview

This is the second of the Java Collection Class parsing, on a [interview must be: ArrayList source Analysis (JDK8)], we chatter ArrayList, today to continue to say LinkedList. In the interview, the two brothers often compare them.

They can be said to be a list of two different implementations of the interface, ArrayList and deletion efficiency is low, but the efficiency of the check is high.
and LinkedList just the opposite, additions and deletions because you do not need to move the underlying array data , its bottom is linked list implementation, only need to modify the link table node pointer, so the efficiency is high .
And the change and check , all need to navigate to the target node, so the efficiency is low .

Before opening, say again Collection.toarray ();
This method is very important, whether it is ArrayList, LinkedList in the batch add, will first transform the array to do. Because arrays can be traversed directly by the for loop. more convenient and efficient

The routine is still,
This article will start from a few common methods to read LinkedList source code.
Read the source code according to the order of the Common API (add, delete,->, check) from the construction method , and will explain the meaning of some variables involved in reading method. Understand the characteristics of LinkedList, the application of the scene.

If this article has incorrect conclusions, statements, please put forward and I discuss, common progress, thank you. Overview

In a nutshell, LinkedList is a thread -insecure, two-way linked list that allows elements to be null .
Its underlying data structure is linked list, it realizes List<e>, Deque<e>, cloneable, java.io.Serializable interface, it realizes Deque<e>, so it can also serve as a two-terminal queue. and ArrayList ratio, not implemented randomaccess so its following subscript, random access element speed is slower .

Because of its underlying data structure is linked list, so it can be imagined, its additions and deletions only need to move the pointer, so the time efficiency is high . There is no need for bulk capacity expansion , there is no need to reserve space , so space efficiency is higher than ArrayList.

The disadvantage is that the need for random access to elements, time efficiency is very low , although the underlying in accordance with the Subscript query node, will be judged according to the index node in the first half or the second half of the paragraph, and then decide whether the order or reverse query to improve the efficiency of time . However, with the increase of N, the overall time efficiency is still very low.

When each increment, delete, will revise Modcount. Construction Method

    Collection element quantity
    transient int size = 0;
    Chain header node
    transient node<e> first;
    Link tail node
    transient node<e> last;
    It's nothing
    . Public LinkedList () {
    }
    //Call public     Boolean addall (collection< extends e> c)  Inserts all elements of the set C into the list public
    LinkedList (collection< extends e> c) {this
        ();
        AddAll (c);
    }

The construction method is basically not doing anything. nodes node structure:

    private static class Node<e> {
        E item;//element value
        node<e> next;//back node
        node<e> predecessor node C21/>node (node<e> prev, E element, node<e> next) {
            This.item = element;
            This.next = Next;
            This.prev = prev;
        }
    

As you can see, this is a two-way list. Add 1 AddAll

Then, first of all, AddAll.

AddAll, add the public boolean addall (collection<? extends e> c) {return AddAll (size, c) in the tail batch, insert subscript with size, inserting in Set C There are elements}//with index as caret, insert all elements in Set C public boolean addall (int index, COLLECTION&LT;? extends e> c) {Checkpositionindex ( Index)//check out of bounds [0,size] closed interval object[] a = C.toarray ();//get target set array int numnew = a.length;//number of new elements if (numnew = =

    0)//If the new element quantity is 0, does not increase, and returns false return false;  Node<e> pred, SUCC;  The predecessor node of the index node, the back node if (index = = size) {//append data SUCC = null at the end of the list;
        The rear node of the size node (team tail) must be null pred = last;//The predecessor node is the team tail} else {SUCC = node (index);//Remove the index node as the back node pred = Succ.prev; The predecessor node is that the previous node of the Index node}//list is incremented in bulk, by a for loop traversing the original array, followed by an Insert node operation.
        Contrast ArrayList is the system.arraycopy to complete the bulk increment for (Object o:a) {//traverse the node to be added.
        @SuppressWarnings ("unchecked") E = (e) o; node<e> NewNode = new Node<> (pred, E, null);//previous node and element value E, build new node, if (pred = null)//If the predecessor node is empty, description
      It's a head knot.      i = NewNode;
        else//otherwise the predecessor node is set to ask the new node Pred.next = NewNode; pred = newnode;//step, the current node is a predecessor node, prepare for the next add node} if (succ = = null) {//loop at the end, if judged, if the rear node is null.
        This is append at the end of the team. last = pred;

    Set the tail node} else {pred.next = SUCC;//Otherwise the node inserted in the team, update the predecessor node Succ.prev = pred;//Update the predecessor node of the Post node}  Size + = Numnew;  Modify quantity size modcount++;
Modify Modcount return true; /////According to index query out node, node<e> node (int index) {//Assert Iselementindex (index);//When a node is fetched by subscript, (increase, check), according to IND
        Ex is in the first half or the second half of a binary to enhance query efficiency if (Index < (size >> 1)) {node<e> x = i;
        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; } private void Checkpositionindex (int index) {if (!ispositionindex (index)) throw new IndexoutofboundSexception (outofboundsmsg (index));  Private Boolean ispositionindex (int index) {return index >= 0 && index <= size; Check on insert, subscript can be size [0,size]}

Summary: The number of linked list increases, is by the for loop traversal of the original array, followed by the Insert node operation . Contrast ArrayList is the time to get a node through the System.arraycopy by a batch increment, (add Select), which is based on the index in the first half or the second half of a binary to improve query efficiency 2 Inserting a single node add

Insert a node at the end: Add Public
Boolean add (E e) {
    linklast (e);
    return true;
}

The new node is generated and inserted at the end of the list to update the Last/first node.
void Linklast (e e) { 
    final node<e> l = last;///Records the original tail node
    final node<e> newNode = new node<> (l, E, NULL)//The predecessor node with the original tail node as the new node last
    = newnode;//Update Tail node
    if (L = = null)//Packages linked list is empty linked list, need extra update header node First
        = NewNode;
    else//Otherwise, the back node of the original tail node is updated with the current tail node (new node)
        l.next = NewNode;
    size++;//Modify Size
    modcount++;//modify Modcount
}
    At the specified subscript, index, insert a node public
    void Add (int index, E element) {
        Checkpositionindex (index); check if subscript is out of bounds [0,size]
        if (index = = size)//After the tail node insert
            linklast (element);
        else//inserts
            linkbefore (element, node (index)) in the middle
    ;
    Before the SUCC node, insert a new node e
    void Linkbefore (e E, node<e> succ) {
        //assert succ!= null;
        Save the predecessor node of the back node
        final node<e> pred = Succ.prev;
        Pre-and post-node and element value E constructs a new node
        final node<e> = NewNode = new Node<> (pred, E, succ);
        The new node, SUCC, is the predecessor node of the original node
        succ.prev = NewNode;
        if (pred = = null)//If the previous predecessor node is empty, the SUCC is the original header knot. So the new node is now the head node first
            = NewNode;
        else//otherwise the rear node of the building predecessor node is the new
            pred.next = NewNode;
        size++;//Modify Quantity
        modcount++;//modify Modcount
    }

Summary:
* Increase will definitely modify Modcount Delete Remove

Delete: Remove target node public E remove (int index) {checkelementindex (index);//check for cross-border subscript [0,size] Return Unlink (node (index)
    //delete a node from the linked list}//delete x node E unlink (node<e> x) {//assert x!= null from the list; Final E element = X.item; The element value of the current node is final node<e> next = X.next; The back node of the current node final node<e> prev = x.prev;//The current node's predecessor node if (prev = = null) {//If the predecessor node is empty (indicates that the current node is originally a header) fi  rst = next;
        The header is equal to the back node} else {prev.next = next; X.prev = null;
        Put the current node's predecessor node empty} if (next = = null) {//If the trailing node is empty (indicating that the current node is originally the tail node) last = prev//The tail node is the predecessor node} else {
        Next.prev = prev; X.next = null;//The current node's back node to empty} X.item = null; Empty size--the current element value;  Revise quantity modcount++; Modify Modcount return element; Returns the removed element value} private void Checkelementindex (int index) {if (!iselementindex (index)) throw new Ind
    Exoutofboundsexception (outofboundsmsg (index)); }//Subscript [0,size) Private Boolean IsEleMentindex (int index) {return index >= 0 && index < size;
 }

Delete the specified node in the linked list:

    Because you want to consider the null element, it is also a separate traversal of the public boolean remove (Object o) {if (o = = null) {//If the null node is to be deleted (see from Remove and add)  Out, allowing the element to be null)//traversing each node in contrast for (node<e> x = i x!= null; x = x.next) {if (X.item = null)
                    {unlink (x);
                return true; }} else {for (node<e> x = i x!= null; x = X.next) {if (O).
                    Equals (X.item)) {unlink (x);
                return true;
    }} return false;
        ///To remove node X from the list, delete E unlink (node<e> x) {//assert x!= null; Final E element = x.item;//Continuation element value for return final node<e> next = x.next;//Save the current node's back node final node<e> p Rev = x.prev;//Front node if (prev = = null) {//predecessor node is null, first = next;//is next} else {//otherwise before update
            The back node of the node Prev.next = next;X.prev = null;//Remember to delete the node's predecessor NULL}//If the trailing node is null, it is the tail node if (next = null) {last = P
        Rev;
            else {//otherwise update the predecessor node of the post node Next.prev = prev;
        X.next = null;//Remember to delete the node's back node to null}//to null the element value of the deletion node so that GC X.item = null; size--;//Modify the size modcount++;//modify Modcount return element;//returns the deleted element value}

Delete also will certainly revise Modcount. Press the subscript to delete, also first according to index node, and then go to the linked list unlink off this node. By deleting the elements, you first go through the list to find out if there is a node, so you can iterate over it two times and then unlink it, taking into account the allowable null value. Change Set

Public E Set (int index, E element) {
    Checkelementindex (index);/check for Cross-border [0,size)
    node<e> x = Node (index); Remove the corresponding node
    E oldval = x.item;//Save the old value for return
    X.item = element;//overwrite old value with new value
    return oldval;//back old value
}

change is based on the index to find node, and then replace the value , change does not modify Modcount search get

Query node based on index

Public E get (int index) {
    checkelementindex (index);//To determine whether the line is crossed [0,size) return
    node (index). Item;//Call Node () method Remove node nodes,
}

Query subscript based on the node object

    public int indexOf (Object o) {
        int index = 0;
        if (o = = null) {//If the target object is null//traversal of the list for
            (node<e> x = A, x!= null; x = x.next) {
                if (X.item = = NULL ) return
                    index;
                index++
            }
        } else {////traversal list for
            (node<e> x = i x!= null; x = x.next) {
                if (o.equals (X.item)) return
                    index;
  index++
            }
        }
        return-1;
    }

Traverse the list from tail to head to find the node with the target element value O

    public int LastIndexOf (Object o) {
        int index = size;
        if (o = = null) {for
            (node<e> x = last; x!= null; x = X.prev) {
                index--;
                if (X.item = = null) return
                    index;
            } "else {for"
            (node<e> x = last; x!= null; x = X.prev) {
                in dex--;
                if (O.equals (X.item)) return
                    index;
            }
        return-1;
    }

Check not modify Modcount ToArray ()

Let's also take a look at ToArray (). After all, it's a high-frequency API.

    Public object[] ToArray () {
        //new a new array and then traverses the linked list, with each element in an array, returning
        object[] result = new Object[size];
        int i = 0;
        for (node<e> x = i x!= null; x = x.next)
            result[i++] = X.item;
        return result;
    }
Summary:

LinkedList is a two-way list. The chain list is increased in bulk by traversing the original array by A For loop, followed by the Insert node operation . The contrast ArrayList is accomplished by system.arraycopy to bulk additions. The increase will certainly modify the Modcount.

When a node is fetched by subscript, (add Select), a binary is made based on whether the index is in the first half or the second half to improve query efficiency

Delete also will certainly revise Modcount. Press the subscript to delete, also first according to index node, and then go to the linked list unlink off this node. By element deletion, will first go through the linked list to find whether there is the node, if so, go to the list on the unlink off this node. Change is also based on index to find node, and then replace the value. Change not to modify Modcount. The search itself is based on index to find node. So its crud operations involve finding node operations based on the index.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.