Learning List interface Implementation class ArrayList Vector LinkedList
The most common and most important of the implementation classes of the list interface are these three: ArrayList, Vector, LinkedList.
The definitions of these three classes in the JDK:
public class Arraylist<e> extends abstractlist<e> implements List<e>, Randomaccess, Cloneable, java.io.serializable{
<span style= "FONT-SIZE:18PX;" >public class vector<e> extends abstractlist<e> implements List<e>, Randomaccess, Cloneable, java.io.serializable{</span>
<span style= "FONT-SIZE:18PX;" >public class linkedlist<e> extends abstractsequentiallist<e> implements LIST<E> Deque<e>, cloneable, java.io.serializable{ transient int size = 0;</span>
From these three class definitions, you can see some information:
- Three have directly implemented the Abstractlist this abstract class
- ArrayList and vectors implement the Randomaccess interface, and LinkedList No, what does that mean? In the JDK, the Randomaccess interface is an empty interface, so it doesn't really make sense, it's a tag that tags this class to support fast random access, so ArrayList and vectors support random access, but LinkedList doesn't support
- The Serializbale interface indicates that they all support serialization.
The following is a detailed list of the three implementations.
View the implementation of the source code will find these three inside, ArrayList and vector use the implementation of the array, equivalent to encapsulate the operation of the logarithmic group. That's why they can support fast random access, and to say the same thing, all array-based data structures in the JDK can support fast random access.
ArrayList and vector implementations almost all use the same algorithm, their main difference is that ArrayList does not have any method to synchronize, so it is not thread-safe, and most of the vector methods are thread-synchronized so it is thread-safe.
LinkedList uses the data structure of a two-way circular linked list. Because it is based on the linked list, it is not possible to implement random access, only sequential access, which also formally does not implement the Randomaccess interface reason.
Formally due to the different data structures used by ArrayList, vectors and LinkedList, it is destined that they apply to completely different scenarios.
By reading the source code of these several classes, we can see the difference in their implementation. ArrayList and vectors are basically the same, we compare them with ArrayList and LinkedList.
Add an element at the end
The Add method in ArrayList is implemented as follows:
<span style= "FONT-SIZE:18PX;" >/** * Appends the specified element to the end of this list. * Add elements to the end of the array * @param e element to being appended to the This list * @return <tt>true</tt> (as specified by { @link Collection#add}) */Public Boolean add (E e) { ensurecapacityinternal (size + 1); Increments modcount!! elementdata[size++] = e; return true; } </span>
This method does two things, first ensuring that the array space is large enough, and then adding elements at the end of the array and passing the Post + + to complete the size+1
From this code it can be seen that if the array space is large enough, then just the add operation of the array is O (1) performance, very efficient.
Look at the implementation of the Ensurecapacityinternal method:
private void ensurecapacityinternal (int mincapacity) { modcount++; Overflow-conscious Code if (Mincapacity-elementdata.length > 0) grow (mincapacity); }
/** * Increases the capacity to ensure so it can hold at least the * number of elements specified by the minimum Capacity argument. * * @param mincapacity the desired minimum capacity * /private void grow (int mincapacity) { //Overflow-c onscious code int oldcapacity = elementdata.length; int newcapacity = oldcapacity + (oldcapacity >> 1); if (newcapacity-mincapacity < 0) newcapacity = mincapacity; if (newcapacity-max_array_size > 0) newcapacity = hugecapacity (mincapacity); Mincapacity is usually close to size, so this is a win: Elementdata = arrays.copyof (Elementdata, newcapacity);
}
As you can see, if the array space is not enough, then this method will do the array expansion and the group copy operation, see the 11th row, the JDK uses the shift operator to expand the calculation, >>1 to the right one represents the other 2, so newcapacity is the expansion of the original 1.5 times times.
PS: The code here is the implementation of JDK1.7, JDK1.7 to 1.6 of a lot of code to optimize, such as the above expansion code, the 11th line in the JDK1.6 is directly in addition to 2, obviously, the shift operation to be more efficient.
Look at the Add method in LinkedList:
<span style= "FONT-SIZE:18PX;" >/** * Appends the specified element to the end of this list. * add element to last * <p>this method is equivalent to {@link #addLast}. * * @param e element to is appended to the list * @return {@code true} (as specified by {@link collection#add})
*/Public Boolean add (E e) { linklast (e); return true; } </span>
/** * Links e as last element. * /void Linklast (E e) { final node<e> l = last; Final node<e> NewNode = new node<> (l, E, null); last = NewNode; if (L = = null) First = NewNode; else l.next = NewNode; size++; modcount++; }
Node (node<e> prev, E element, node<e> next) { This.item = element; This.next = Next; This.prev = prev; }
From this add code can be seen, linkedlist because of the use of the chain list, so do not need to expand, directly add elements to the list at the end of the new element to point to the previous last element, and the last element point to the new element. This is also an O (1) performance.
Insert an element at any location
The implementation in ArrayList is as follows:
<span style= "FONT-SIZE:18PX;" >/** * Inserts the specified element at the specified position in this * list. Shifts the element currently at, if any, and * any subsequent elements to the right (adds one to their I ndices). * * @param index index at which the specified element was to being inserted * @param element element to be Inserted
* @throws indexoutofboundsexception {@inheritDoc} * /public void Add (int index, E element) { Rangecheckforadd (index); Ensurecapacityinternal (size + 1); Increments modcount!! System.arraycopy (Elementdata, index, Elementdata, index + 1, size-index); Elementdata[index] = element; size++; } </span>
This code, first check the array capacity, capacity is not enough to expand the first, and then the index after the array to move backward, and finally put a new element at the index position. Since an array is a contiguous memory space, inserting at any location causes the subsequent array to move a bit later, and it is clear that if there is a large number of random insertions, the array copy operation will be expensive, and the higher the array replication overhead is, the greater the insertion cost.
Implementation in LinkedList:
<span style= "FONT-SIZE:18PX;" >/** * Inserts the specified element at the specified position on this list. * Shifts the element currently at, if any, and any * Subsequent elements to the right (adds one to their indices). * * @param index index at which the specified element was to being inserted * @param element element to be Inserted
* @throws indexoutofboundsexception {@inheritDoc} * /public void Add (int index, E element) { Checkpositionindex (index); if (index = = size) linklast (element); else Linkbefore (element, node (index)); } </span>
/** * Inserts element e before Non-null Node succ. * /void Linkbefore (e E, node<e> succ) { //assert SUCC! = null; Final node<e> pred = Succ.prev; Final node<e> NewNode = new Node<> (pred, E, succ); Succ.prev = NewNode; if (pred = = null) First = NewNode; else pred.next = NewNode; size++; modcount++; }
This code, take the original index node of the predecessor, become the precursor of the new node, while the original index into a new node after the drive, so that the new node is inserted. This is the advantage of the list, there is no data copy operation, the performance and in the last insert is the same.
Summary: From the above analysis of the source code can see the three list of the implementation of some typical scenarios, if often do random insertion of the array, especially before the comparison of inserts, then LinkedList performance advantage is very obvious, and if all is just the end of the insertion, then ArrayList more dominant, If thread safety is required, use a vector or create a thread-safe ArrayList.
In the use of array-based implementation of ArrayList and vectors we want to specify the initial capacity, because we also see in the source code, in addition, the first to make a capacity judgment, if the capacity is not enough to create a new array, but also to copy the original array of data into the new array, This process can reduce efficiency and waste resources.
List interface Implementation class-arraylist, Vector, LinkedList set of deep learning and source parsing