Source code analysis of the collections list of Java Collection Series

Source: Internet
Author: User

Source code analysis of the collections list of Java Collection Series
I. Introduction to tranquility list

A sort list is an ordered sequence that allows efficient insert and remove operations at any location. It is implemented based on a two-way linked list.

Ps: Here is a question about whether or not the data structure of the sorted list is a circular two-way linked list. Many articles on the Internet have said it is a loop, in some articles, I read the source code and think it should not be a loop?

For example, the Code of deleting a node at the end of the list:

 

 private E unlinkLast(Node
 
   l)   {        final E element = l.item;        final Node
  
    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;    }
  
 

 

After the last node l is deleted, the next of the node prev prior to l is set to null without pointing to the head node. I don't know if it is because of the code version (my source code is obtained in the downloaded jdk1.8.0 _ 45 file). If you see the reason, I hope you can help me solve it!

The basic structure of the node is defined in the source code:

 

Private static class Node
 
  
{E item; // indicates the Node value contained by the Node.
  
   
Next; // represents the next Node of the current Node
   
    
Prev; // indicates the previous Node of the current Node (Node
    
     
Prev, E element, Node
     
      
Next) {this. item = element; this. next = next; this. prev = prev ;}}
     
    
   
  
 

 

The category list class diagram is as follows:

A two-way linked list inherited from AbstractSequentialList. It can also be operated as a stack, queue, or double-end queue.
The listlist interface can be used to operate queues.
Consumer List implements the Deque interface, which can be used as a dual-end queue.
Javaslist implements the Cloneable interface, which overwrites the function clone () and can be cloned.
The serialize List implements the java. io. Serializable interface, which means that the serialize List supports serialization and can be transmitted through serialization.
The synchronized list is not synchronous.

Ii. Source Code Analysis of the shortlist
Public class upload list
 
  
Extends AbstractSequentialList
  
   
Implements List
   
    
, Deque
    
     
, Cloneable, java. io. serializable {// when the Serilizable interface is implemented, the transient keyword is added before the attribute that does not need to be serialized. When the object is serialized, this attribute is not serialized to the specified destination. Transient int size = 0; // point to the first Node transient Node
     
      
First; // point to the last Node transient Node
      
        Last; // construct an empty list public writable list () {}// construct a list public writable list (Collection
       C) {this (); addAll (c) ;}// use the Node with the Node value e as the first Node private void linkFirst (E e) {final Node
       
         F = first; // construct a Node final Node whose prev value is null, next is f, and Node value is e.
        
          NewNode = new Node <> (null, e, f); // use newNode as the first Node first = newNode; // if there is no node after newNode, use newNode as the last node. if (f = null) last = newNode; // otherwise, newNode is assigned to its prev else f. prev = newNode; // The list Length plus a size ++; modCount ++;} // use the Node with the Node value e as the last Node void linkLast (E e) {final Node
         
           L = last; // construct a Node final Node whose prev value is l, next is null, and Node value is e
          
            NewNode = new Node <> (l, e, null); last = newNode; if (l = null) first = newNode; else l. next = newNode; size ++; modCount ++;} // insert Node e void linkBefore (E e, Node
           
             Succ) {final Node
            
              Pred = succ. prev; // use the Node before succ and succ as its prev and next final Node
             
               NewNode = new Node <> (pred, e, succ); // use newNode as the prev succ of succ. prev = newNode; // if the original succ is the first node, set newNode as the first node if (pred = null) first = newNode; else pred. next = newNode; size ++; modCount ++;} // release non-empty first Node f private E unlinkFirst (Node
              
                F) {final E element = f. item; final Node
               
                 Next = f. next; f. item = null; f. next = null; // help GC // set the node after the first node to the first node first = next; if (next = null) last = null; else next. prev = null; size --; modCount ++; return element;} // release non-empty end Node l private E unlinkLast (Node
                
                  L) {final E element = l. item; final Node
                 
                   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;} // Delete non-empty Node x E unlink (Node
                  
                    X) {final E element = x. item; final Node
                   
                     Next = x. next; // The final Node after x
                    
                      Prev = x. prev; // if (prev = null) {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;} // return the value of the first Node in the list. public E getFirst () {final Node
                     
                       F = first; if (f = null) throw new NoSuchElementException (); return f. item;} // return the value of the final Node element at the end of the list public E getLast () {final Node
                      
                        L = last; if (l = null) throw new NoSuchElementException (); return l. item;} // remove the first public E removeFirst () {final Node
                       
                         F = first; if (f = null) throw new NoSuchElementException (); return unlinkFirst (f) ;}// Delete the End Node public E removeLast () {final Node
                        
                          L = last; if (l = null) throw new NoSuchElementException (); return unlinkLast (l) ;}// insert node e public void addFirst (E e) in the first part of the list) {linkFirst (e);} // Insert the node e public void addLast (E e) {linkLast (e);} at the end of the list );} // determine whether the list contains the element o public boolean contains (Object o) {return indexOf (o )! =-1;} // return list Length size public int size () {return size;} // Insert the public boolean add (E e) element at the end of the list) {linkLast (e); return true;} // Delete the public boolean remove (Object o) {if (o = null) {for (Node
                         
                           X = first; x! = Null; x = x. next) {if (x. item = null) {unlink (x); return true ;}} else {for (Node
                          
                            X = first; x! = Null; x = x. next) {if (o. equals (x. item) {unlink (x); return true ;}} return false ;}// add all the elements in set c to the end of the list public boolean addAll (Collection
                           C) {return addAll (size, c);} // inserts the elements in set c into the public boolean addAll (int index, Collection
                           C) {// determine the validity of the insert position checkPositionIndex (index); Object [] a = c. toArray (); int numNew =. length; if (numNew = 0) return false; Node
                           
                             Pred, succ; if (index = size) {// description Insert the set element succ = null at the end of the list; pred = last;} else {// otherwise, locate the node succ = node (index); pred = succ where the index is located. prev;} for (Object o: a) {@ SuppressWarnings (unchecked) E e = (E) o; Node
                            
                              NewNode = new Node <> (pred, e, null); if (pred = null) first = newNode; else pred. next = newNode; pred = newNode;} if (succ = null) {last = pred;} else {pred. next = succ; succ. prev = pred;} size + = numNew; modCount ++; return true ;}// delete all nodes in the list public void clear () {for (Node
                             
                               X = first; x! = Null;) {Node
                              
                                Next = x. next; x. item = null; x. next = null; x. prev = null; x = next;} first = last = null; size = 0; modCount ++ ;} // obtain the value of the element public E get (int index) {checkElementIndex (index); return node (index) at the specified index position ). item;} // Replace the element value of the Node at the specified index position with public E set (int index, E element) {checkElementIndex (index); Node
                               
                                 X = node (index); E oldVal = x. item; x. item = element; return oldVal;} // Insert the element e public void add (int index, E element) {checkPositionIndex (index) before the specified index location ); if (index = size) linkLast (element); else linkBefore (element, node (index);} // Delete the public E remove (int index) element at the specified position) {checkElementIndex (index); return unlink (node (index);} // determines whether the elements at the specified index position have private boolean isElementIndex (int index) {return I Ndex> = 0 & index <size;} private boolean isPositionIndex (int index) {return index> = 0 & index <= size ;} // construct IndexOutOfBoundsException details private String outOfBoundsMsg (int index) {return Index: + index +, Size: + size;} private void checkElementIndex (int index) {if (! IsElementIndex (index) throw new IndexOutOfBoundsException (outOfBoundsMsg (index);} private void checkPositionIndex (int index) {if (! IsPositionIndex (index) throw new IndexOutOfBoundsException (outOfBoundsMsg (index);} // return the Node at the specified index location
                                
                                  Node (int index) {// here is a tip, when the index
                                 
                                   > 1) {Node
                                  
                                    X = first; for (int I = 0; I <index; I ++) x = x. next; return x;} else {Node
                                   
                                     X = last; for (int I = size-1; I> index; I --) x = x. prev; return x ;}/// returns the position where o appears for the first time in the list. If it does not exist,-1 public int indexOf (Object o) {int index = 0 is returned; if (o = null) {for (Node
                                    
                                      X = first; x! = Null; x = x. next) {if (x. item = null) return index; index ++ ;}} else {for (Node
                                     
                                       X = first; x! = Null; x = x. next) {if (o. equals (x. item) return index; index ++;} return-1 ;}// reverse search, returns the position where the first occurrence of o, -1 public int lastIndexOf (Object o) {int index = size; if (o = null) {for (Node
                                      
                                        X = last; x! = Null; x = x. prev) {index --; if (x. item = null) return index ;}} else {for (Node
                                       
                                         X = last; x! = Null; x = x. prev) {index --; if (o. equals (x. item) return index ;}} return-1;} // obtain the element value of the first Node in the list public E peek () {final Node
                                        
                                          F = first; return (f = null )? Null: f. item;} // obtain the value of the first node in the list. If it is null, an exception public E element () {return getFirst () ;}// retrieves the first node, if it is null, null is returned. If it is not null, its element value is returned and the first Node public E poll () {final Node is deleted.
                                         
                                           F = first; return (f = null )? Null: unlinkFirst (f);} // retrieves the first node. If it is null, an exception is thrown. If it is not null, its element value is returned and the first node public E remove () is deleted () {return removeFirst ();} // add the node e public boolean offer (E e) {return add (e);} at the end of the list );} // insert node e public boolean offerFirst (E e) {addFirst (e); return true;} // insert node e public boolean offerLast (E) at the end of the list) {addLast (e); return true;} public E peekFirst () {final Node
                                          
                                            F = first; return (f = null )? Null: f. item;} // obtain the value of the element at the end of the list Node public E peekLast () {final Node
                                           
                                             L = last; return (l = null )? Null: l. item;} public E pollFirst () {final Node
                                            
                                              F = first; return (f = null )? Null: unlinkFirst (f);} public E pollLast () {final Node
                                             
                                               L = last; return (l = null )? Null: unlinkLast (l);} // public void push (E e) {addFirst (e);} // public E pop () {return removeFirst ();} // Delete the public boolean removeFirstOccurrence (Object o) {return remove (o);} // reverse search, delete the public boolean removeLastOccurrence (Object o) {if (o = null) {for (Node
                                              
                                                X = last; x! = Null; x = x. prev) {if (x. item = null) {unlink (x); return true ;}} else {for (Node
                                               
                                                 X = last; x! = Null; x = x. prev) {if (o. equals (x. item) {unlink (x); return true ;}} return false ;}
                                               
                                              
                                             
                                            
                                           
                                          
                                         
                                        
                                       
                                      
                                     
                                    
                                   
                                  
                                 
                                
                               
                              
                             
                            
                           
                          
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
        
       
      
     
    
   
  
 
Iii. Several notes about the vertex list 1. Pay attention to the Node in the source code Node (int index) method:
    Node
 
   node(int index)     {        if (index < (size >> 1))         {            Node
  
    x = first;            for (int i = 0; i < index; i++)                x = x.next;            return x;        }        else        {            Node
   
     x = last;            for (int i = size - 1; i > index; i--)                x = x.prev;            return x;        }    }                   
   
  
 

This method returns the node at the specified position in the two-way linked list, and there is no subscript index in the linked list. to specify the element at the position, we need to traverse the linked list. from the implementation of the source code, we can see an acceleration action. In the source code, compare the index with half of the size. If the index Size/2, just traverse from the position size to the position index. This reduces unnecessary traversal.

2. Differences between the rule list and ArrayList:

The role list and ArrayList have their own advantages and disadvantages in terms of performance and have their respective advantages and disadvantages. They are summarized as follows:

  • ArrayList implements a dynamic array-based data structure. The ArrayList is based on the linked list data structure.
  • The random list does not support efficient random element access.
  • The space waste of ArrayList is mainly reflected in the reserved capacity space at the end of the list. The space consumption of the list is reflected in that each of its elements consumes a considerable amount of space, in terms of storage density, the ArrayList is better than the sort list.

    In short, when the operation is to add data after a column of data rather than in the front or middle, and needs to randomly access the elements in it, the use of ArrayList will provide better performance, when you add or delete data in front or middle of a column of data and access the elements in the column in sequence, you should use the sort list.

    3. The allowed element in the rule list is null.

    The source code is as follows:

     

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

     

    4. Basic usage of consumer list:

    We recommend that you describe the basic usage of the shortlist blog.

     

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.