Set (ii) LinkedList

Source: Internet
Author: User

In the previous article explained the ArrayList, this article explains the LinkedList realization.

LinkedList is based on a linked list , so let's start by explaining what a list is. The list was originally a C/s + + concept, a linear storage structure, meaning that the data to be stored in a storage unit inside, in addition to storing the data to be stored, it also stores the address of its next storage unit (the address of the next storage unit is necessary, Some storage structures also hold the address of their previous storage unit, and each time the data is looked up, the address of the next storage unit in a storage unit is searched for the storage unit behind it.

So it may be a little abstract, first of all, LinkedList is a doubly linked list, two-way list I think there are two points meaning:

1. Any storage unit in the linked list can be obtained by means of forward or backward addressing to its previous storage unit and subsequent storage unit

2, the last node of the tail node of the linked list is the head node of the linked list, and the previous node of the list's head node is the tail of the linked list.

LinkedList since it is a doubly linked list, there must be a storage unit that looks at the basic storage unit of LinkedList, which is an inner class in LinkedList:

private static class Entry<e> {E element; Entry<e> Next; Entry<e> Previous, ...}

See the "E element" in LinkedList's entry, which is the data it really stores. "Entry<e> Next" and "Entry<e> previous" represent the reference address of the previous storage unit of this storage unit and the reference address of the latter storage unit. The diagram shows that:

Four points of concern on the LinkedList answer

Focus Point Conclusion
LinkedList whether NULL is allowed Allow
LinkedList whether duplicate data is allowed Allow
Whether the LinkedList is orderly Ordered
LinkedList is thread safe Non-thread safe

adding elements

First look at the LinkedList add an element is how to do, if I have a piece of code:

1 public static void main (string[] args) 2 {3     list<string> List = new Linkedlist<string> (); 4     List.add ("111"); 5     List.add ("222"); 6}

row by line analysis of the main function of the three lines of code is how to execute, first of all, the 3rd line, look at the source of LinkedList:

1 public class Linkedlist<e> 2     extends abstractsequentiallist<e> 3     implements List<e>, Deque <e>, cloneable, java.io.Serializable 4 {5     private transient entry<e> header = new entry<e> (null, NU ll, NULL);  6     private transient int size = 0; 7  8     /** 9      * Constructs an empty list.10      */11 public     LinkedList () {         Header.next = header.previous = header;13     }14     ... 15}

See, new A entry out named Header,entry inside the previous, element, Next are null, when the constructor is executed, the values of previous and next are set to the reference address of the header, Or in the form of a drawing. The 32-bit JDK has a word length of 4 bytes, and the current 64-bit JDK generally uses 4 word lengths, so it is in 4 words. The word length of the header reference address is 4 bytes, assuming that it is 0x00000000, then after executing "list<string> List = new linkedlist<string> ()" You can say:

Then look at line 4th add a string "111" to do what:

1 public boolean Add (E e) {2 Addbefore (e, header); 3     return true;4}
1 Private entry<e> Addbefore (e E, entry<e> Entry) {2 entry<e> newEntry = new Entry<e> (e, Entry, en try.previous); 3 NewEntry.previous.next = newentry;4 newEntry.next.previous = newentry;5 size++;6 modcount++;7 return NEWENTRY;8}

The 2nd line new A entry out, may not be very good to understand, according to entry's constructor, I put this sentence "translated" a bit, may be good to understand:

1, newentry.element = e;

2, newentry.next = Header.next;

3, newentry.previous = header.previous;

Header.next and header.previous have seen, are 0x00000000, then assume that the new out of this entry address is 0x00000001, continue to draw the expression:

A total of five steps, each step of the operation steps are expressed in numbers:

1, the new entry element is assigned a value of 111;

2, the new entry next is the header of the Next,header next is 0x00000000, so the new entry next namely 0x00000000;

3, the new entry previous is the header of the Previous,header previous is 0x00000000, so the new entry next namely 0x00000000;

4, "NewEntry.previous.next = NewEntry", the first is the previous of NewEntry, because NewEntry previous for 0x00000000, So Newentry.previous said that Header,header's next is newentry, that is, the header of next is 0x00000001;

5, "newEntry.next.previous = NewEntry", and 4, the header of the previous set to 0x00000001;

Why do you do this? Remember the two-way list of two characteristics, one is that any node can be forward and backward addressing, the second is the entire chain of the head of the previous represents the tail of the list of entry, the end of the list of the link is the head of the list entry. Now the chain of the head is 0x00000000 this entry, the tail of the chain is 0x00000001, you can look at the picture to see, think about whether it meets these two conditions.

Finally look at add a string "222" What to do, assuming that the address of the new entry is 0x00000002, drawing means:

or the implementation of the 5 steps, each step of the figure is marked out, as long as you want to know previous, next each of which node is not a problem.

At this point, adding a string "111" and a string "222" to a LinkedList is complete. It should be easier to understand the doubly linked list from this diagram:

1, the middle of the value of the entry,previous is 0x00000000, that is, the value of Header;next is 0x00000002, that is, tail, which is any one entry can either forward to find entry, can also look backwards entry

2, the previous value of the head entry is 0x00000002, that is, tail, this is the doubly linked list in the head entry previous point to the tail entry

3, the next value of the tail entry is 0x00000000, that is, the header, which is the two-way list in the tail entry of the next point is the head entry

viewing elements

Take a look at how the LinkedList code is written:

Public E get (int index) {    return Entry (index). element;}
1 private entry<e> Entry (int index) {2     if (Index < 0 | | index >= size) 3         throw new Indexoutofboundsex Ception ("Index:" +index+ 4                                             ", Size:" +size); 5     entry<e> E = header, 6     if (Index < (size >> 1)) {7 for         (int i = 0; I <= index; i++) 8
   
    e = E.next; 9     } else {ten for         (int i = size; i > index; i--) one             e = e.previous;12     }13     return e;14}
   

This code shows the benefits of a doubly linked list. The doubly linked list adds a little bit of space consumption (each entry also maintains its pre-entry references), while adding a certain degree of programming complexity, which greatly improves efficiency.

Since LinkedList is a doubly linked list, LinkedList can either look forward or look backwards, and line 6th ~ 12th is: when index is less than half the size of the array (size >> 1 means size/ 2, use the shift operation to improve the efficiency of the Code), look backwards; otherwise, look forward .

In this way, in my data structure there are 10,000 elements, it happens to find the 10,000th element, it does not need to traverse 10,000 times, the backward traversal can be, one can find the element I want.

Delete Element

After reading the add element, let's look at how to delete an element. Like ArrayList, LinkedList supports deleting by element and pressing subscript, which deletes the first element that matches from the beginning. Use the subscript to delete for example, let's say there's a code like this:

1 public static void main (string[] args) 2 {3     list<string> List = new Linkedlist<string> (); 4     List.add ("111"); 5     List.add ("222"); 6     list.remove (0); 7}

That is, I want to delete the "111" element. Take a look at how line 6th is executed:

1 public E Remove (int index) {2     return Remove (Entry (index)); 3}
1 Private e Remove (entry<e> e) {2 if (E = = header) 3     throw new Nosuchelementexception (); 4  5         E result = E.element; 6 e.previous.next = E.next; 7 e.next.previous = e.previous; 8        e.next = e.previous = null; 9        e.element = null;10 size--;11 modcount++;12        return result;13}

Of course, the first thing to find is where the element is, and this is the same as get. Then, it is easier to illustrate it in a drawing way:

Relatively simple, as long as the reference address to find the good, each step of the operation is also detailed in the diagram.

Here I mention that the 3rd, 4th, 5th steps will be deleted entry's previous, element, next are set to NULL, the role of these three steps is to let the virtual machine can reclaim this entry.

However, this problem I extend a little bit deeper: According to the Java Virtual Machine hotspot adopted garbage collection detection algorithm----root node search algorithm, even if previous, element, next is not set to NULL can also be recycled this entry, Because this entry has no place to point to it at this time, tail's previous and the header of next have been changed, so this piece of entry will be treated as "rubbish". Previous, Element, Next is also set to NULL, I think it may be to be compatible with another garbage collection detection algorithm----Reference counting method, the garbage collection detection algorithm, as long as there are mutual references between objects, then this block of memory will not be treated as "garbage".

inserting elements

Inserting elements is not detailed, take a look at the source code of the deleted element:

public void Add (int index, E element) {    Addbefore (element, (index==size. Header:entry (index)));}
Private entry<e> Addbefore (e E, entry<e> Entry) {entry<e> newEntry = new Entry<e> (e, Entry, Entry. previous); NewEntry.previous.next = newentry;newentry.next.previous = Newentry;size++;modcount++;return newEntry;}

If your friends understand the previous content, I think these two methods should be easy for you to understand.

Comparison of LinkedList and ArrayList

The cliché of the problem, here I try to understand their own understanding of this problem, by the way here to the linkedlist of the pros and cons also told.

1, sequential insertion speed ArrayList will be faster, because ArrayList is based on the implementation of the array, the array is in advance new good, as long as the specified location to plug a data is good; LinkedList is different, Each time the order is inserted LinkedList will be a new object, if the object is larger, then new time is bound to grow a bit, plus some reference assignment operation, so the sequential insertion of linkedlist must be slower than ArrayList

2, based on a point, because the linkedlist inside not only maintain the elements to be inserted, but also maintain the entry entry and subsequent entry, if a linkedlist very much, Then LinkedList will consume some more memory than ArrayList.

3, the speed of data traversal, see the last part, here is not detailed, the conclusion is: the use of the most efficient way to traverse the ArrayList, the traversal efficiency of the linkedlist than the traversal efficiency of the high-speed

4, some say that linkedlist do insert and delete faster, this statement is actually inaccurate:

(1) LinkedList do insert, delete time, slow in addressing, fast in only need to change the entry before and after the reference address

(2) ArrayList do insert, delete, slow in the array elements of the bulk copy, fast in addressing

Therefore, if the element to be inserted and deleted is in the first half of the data structure, especially in the front position, the efficiency of linkedlist will be much faster than ArrayList, because ArrayList will bulk copy a large number of elements; For LinkedList, because it is a doubly linked list, inserting a data after the 2nd element and inserting an element after the 2nd element is basically no different in efficiency, but ArrayList because there are fewer elements to bulk copy, The operation speed must catch up with even surpass LinkedList.

From this analysis, if you are very sure that the elements you insert and delete are in the first half, then use LinkedList, and if you are very sure that the elements you delete and delete are in the post-comparison position, consider using ArrayList. If you are not sure where you want to insert and delete? It is recommended that you use the LinkedList bar, because one linkedlist the overall insertion, deletion of the execution efficiency is relatively stable, there is no ArrayList the faster the situation, and then insert the element, it is not good ArrayList will be the expansion, remember, ArrayList the underlying array expansion is an operation that consumes both time and space , and in my article Java code optimization, the 9th has a detailed interpretation.

Finally, everything is on paper, after selecting the list, it is best to do some performance testing, such as in your code context to record the time consumption of the list operation .

Iterations of LinkedList and ArrayList

In my Java Code optimization article, 19th, specifically mentioned, ArrayList uses the most common for loop traversal, linkedlist using a foreach loop is faster, take a look at the definition of the two list:

public class Arraylist<e> extends abstractlist<e>        implements List<e>, Randomaccess, Cloneable, Java.io.Serializable
public class linkedlist<e>    extends abstractsequentiallist<e>    implements List<e>, Deque <e>, Cloneable, java.io.Serializable

Note that ArrayList is implemented Randomaccess interface and LinkedList does not implement this interface, about the role of randomaccess this interface, look at the JDK API saying:

To do this, I write a piece of code to prove this point, note that although the above example uses the iterator, but when doing the Foreach loop, the compiler will use the iterator of this set by default, see the Foreach Loop principle. The test code is as follows:

public class testmain{private static int SIZE = 111111;        private static void Looplist (List<integer> List) {Long startTime = System.currenttimemillis ();        for (int i = 0; i < list.size (); i++) {list.get (i); } System.out.println (List.getclass (). Getsimplename () + "traverse time with normal for loop" + (System.currenttimemillis                ()-StartTime) + "MS");        StartTime = System.currenttimemillis (); for (Integer i:list) {} System.out.println (List.getclass (). Getsimplename () + "use FOREAC    H Loop traversal time is "+ (System.currenttimemillis ()-StartTime) +" MS "); } public static void Main (string[] args) {list<integer> arrayList = new Arraylist<integer> (S        IZE);                list<integer> LinkedList = new linkedlist<integer> ();            for (int i = 0; i < SIZE; i++) {arraylist.add (i);    Linkedlist.add (i);    } looplist (ArrayList);        Looplist (LinkedList);    System.out.println (); }}

I intercepted three run results:

ArrayList use a normal for loop traversal time of 6msArrayList using foreach Loop traversal time 12msLinkedList using normal for loop traversal time 38482msLinkedList using foreach Loop traversal time 11ms
ArrayList use a normal for loop traversal time of 5msArrayList using foreach Loop traversal time 12msLinkedList using normal for loop traversal time 43287msLinkedList using foreach Loop traversal time 9ms
ArrayList use a normal for loop traversal time of 4msArrayList using foreach Loop traversal time 12msLinkedList using normal for loop traversal time 22370msLinkedList using foreach Loop traversal time 5ms

With the JDK API explained, the result is not surprising, and the most important thing to ask is that if you use the normal for loop to traverse the LinkedList, the traversal speed will be very slow.

Thanks to the original: http://www.cnblogs.com/xrq730/p/5005347.html

Set (ii) LinkedList

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.