Source code analysis of javaslist in Java Collection series, and javaslist source code

Source: Internet
Author: User

Source code analysis of javaslist in Java Collection series, and javaslist source code

In the previous article, we analyzed the underlying implementation of ArrayList and learned that the underlying implementation of ArrayList is based on arrays. Therefore, it has the characteristics of fast search modification and slow insertion and deletion. The sort List introduced in this article is another implementation of the List interface. Its underlying layer is implemented based on a two-way linked List. Therefore, it has the characteristics of fast insertion and deletion, and slow query and modification. In addition, the queue and stack functions can also be implemented through operations on the two-way linked list. Shows the underlying structure of the tranquility list.

F indicates header node reference, L indicates tail node reference, and each node in the linked list has three elements, namely, forward node reference (P), value of the node element (E ), references of the successor node (N ). The Node is represented by an internal class Node. Let's look at its internal structure.

// Private static class Node inside the Node <E> {E item; // element Node <E> next; // next Node <E> prev; // The previous Node (Node <E> prev, E element, Node <E> next) {this. item = element; this. next = next; this. prev = prev ;}}

The internal class of Node is actually very simple. There are only three member variables and a constructor. item indicates the value of the Node, next indicates the reference of the next Node, and prev indicates the reference of the previous Node, input these three values through the constructor. Next, let's take a look at the member variables and constructors of the shortlist.

// Set the number of elements transient int size = 0; // the header Node references the transient Node <E> first; // The End Node references the transient Node <E> last; // No parameter constructor public parameter list () {}// the constructor that passes in the external set public parameter list (Collection <? Extends E> c) {this (); addAll (c );}

The listlist holds the reference of the header node and the reference of the tail node. It has two constructor, one is the no-argument constructor and the other is the constructor that passes in the external set. Unlike ArrayList, the initial size of the constructor is not specified in listing list. Check its addition, deletion, modification, and query methods.

// Add (add) public boolean add (E e) {// add linkLast (e); return true;} // add (insert) at the end of the linked list) public void add (int index, E element) {checkPositionIndex (index); if (index = size) {// add linkLast (element) at the end of the linked list );} else {// insert linkBefore (element, node (index) ;}/// Delete (given subscript) public E remove (int index) in the middle of the linked list) {// check whether the subscript is legal checkElementIndex (index); return unlink (node (index);} // Delete (given element) public boolean remove (Object o) {if (o = = Null) {for (Node <E> x = first; x! = Null; x = x. next) {if (x. item = null) {unlink (x); return true ;}} else {// time series table for (Node <E> x = first; x! = Null; x = x. next) {if (o. equals (x. item) {// Delete unlink (x); return true ;}}return false;} // change public E set (int index, E element) {// check whether the subscript is valid checkElementIndex (index); // obtain the Node reference node of the specified underlying object <E> x = Node (index ); // obtain the value of the specified subscript node E oldVal = x. item; // set the node element to the new value x. item = element; // return the previous value return oldVal;} // check public E get (int index) {// check whether the subscript is legal checkElementIndex (index ); // return the return node (index) value of the specified vertex ). item ;}

The method for adding elements to the linked list is to call the linkLast and linkBefore methods. The linkLast method links an element behind the linked list, and the linkBefore method inserts an element between the linked list. You can call the unlink method to delete an element from the linked list. Next we will look at the core code of the insert and delete operations on the linked list.

// Void linkBefore (E e, Node <E> succ) before linking to the specified Node {// obtain the final Node referenced by the previous Node of the given Node <E> pred = succ. prev; // create a new node, the previous Node of the new Node references the reference pointing to the next Node of the previous Node of the given Node // reference pointing to the given Node final Node <E> newNode = new Node <> (pred, e, succ); // point the previous node reference of the given node to the new node succ. prev = newNode; // if the previous node of the given node is empty, it indicates that the given node is the header node if (pred = null) {// point the header node reference to the new node first = newNode;} else {// otherwise, point the next node reference of the previous node of the given node to the new node pred. next = newNode;} // The number of set elements plus a size ++; // The number of modifications plus modCount ++;} // unmount the specified Node E unlink (Node <E> x) {// obtain final E element = x. item; // obtain the reference of the next Node of a given Node. final Node <E> next = x. next; // obtain the reference of the previous Node of a given Node. final Node <E> prev = x. prev; // if the previous node of the given node is empty, it indicates that the given node is the header node if (prev = null) {// point the header node reference to the next node first = next;} else {// point the successor node of the previous node to the successor node prev of the given node. next = next; // empty the previous node of the given node x. prev = null;} // if the next node of a given node is null, the given node is the end node if (next = null) {// point the End Node reference to the previous node of the given node last = prev;} else {// point the forward node reference of the next node to the next node of the given node. prev = prev; x. next = null;} // set the element of the given node to null x. item = null; // The number of elements in the Set minus one size --; // The number of modifications plus one modCount ++; return element ;}

LinkBefore and unlink are representative links and unmount operations. Other links and unlink methods are similar. Therefore, we will focus on linkBefore and unlink methods.

The process diagram of the linkBefore method:

Process Diagram of the unlink method:

The figure above shows that the time complexity of the insert and delete operations on the linked list is O (1), and the search and modify operations on the linked list need to locate the elements in the traverse table, both operations call the node (int index) method to locate the element and see how it locates the element through subscript.

// Obtain the Node <E> node (int index) {// If the subscript is in the first half of the list, check if (index <(size> 1) {Node <E> x = first; for (int I = 0; I <index; I ++) from the beginning) {x = x. next;} return x;} else {// If the subscript is in the second half of the linked list, the Node <E> x = last; for (int I = size-1; i> index; I --) {x = x. prev;} return x ;}}

When positioning by subscript, first judge whether it is in the upper half or lower half of the linked list. If it is in the upper half, it will start from the beginning. If it is in the lower half, it will start from the end, therefore, it takes O (n/2) to perform the search and modify operations based on the lower mark ). You can also implement the single queue, two-way queue, and stack functions through operations on the two-way linked list.

One-way queue operation:

// Obtain the public E peek () {final Node <E> f = first; return (f = null )? Null: f. item;} // obtain the header Node public E element () {return getFirst ();} // the header Node public E poll () {final Node <E> f = first; return (f = null )? Null: unlinkFirst (f);} // remove the header node public E remove () {return removeFirst ();} // Add the node public boolean offer (E e) at the end of the queue) {return add (e );}

Bidirectional queue operations:

// Add public boolean offerFirst (E) {addFirst (e); return true;} // Add public boolean offerLast (e) {addLast (E) at the end ); return true;} // get the header Node public E peekFirst () {final Node <E> f = first; return (f = null )? Null: f. item;} // obtain the End Node public E peekLast () {final Node <E> l = last; return (l = null )? Null: l. item ;}

Stack operation:

// Public void push (E e) {addFirst (e) ;}// public E pop () {return removeFirst ();}

Both one-way queues, two-way queues, and stacks operate the head and end nodes of the linked list. Their implementations are based on addFirst (), addLast (), removeFirst (), removeLast () is similar to linkBefore () and unlink (), but one is to operate on both ends of the linked list and the other is to operate in the middle of the linked list. It can be said that these four methods are special cases of the linkBefore () and unlink () methods, so it is not difficult to understand their internal implementations. I will not discuss them here. At this point, our analysis of the listing list is coming to an end, and we will summarize the highlights in the full text:
1. The consumer list is implemented based on a two-way linked list. Whether it is the addition, deletion, modification, query method, or queue and stack implementation, it can be implemented through the operation node.
2. The capacity list does not need to be specified in advance, because the capacity of the set automatically increases with the addition of elements based on the linked list operation.
3. The memory occupied by the set is automatically reduced after the elements are deleted in the sorted list. You do not need to call the trimToSize () method like the ArrayList method.
4. All methods of the merge list are not synchronized, so it is not thread-safe and should be avoided in the multi-threaded environment.
5. The above analysis is based on JDK1.7. Other versions may be different and cannot be generalized.

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

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.