List summary
Let's first review the frame diagram of List in the Collection:
As can be seen from the figure:
1. List is an interface that inherits the Collection interface and represents an ordered queue.
2. AbstractList is an abstract class that inherits AbstractCollection. AbstractList implements the methods in the List interface except size(), get(int location).
3. AbstractSequentialList is an abstract class that inherits from abstractlist. AbstractSequentialList implements "all methods of operating the linked list according to the index value in the linked list".
4. ArrayList, LinkedList, vector and stack are the four implementation classes of List. Vector is based on jdk1 0. Although synchronization is realized, it is inefficient and no longer used. Stack inherits from vector, so I won't repeat it.
5. LinkedList is a two-way linked list, which can also be used as a stack, queue or double ended queue.
The difference between ArrayList and LinkedList
As we know, the differences between ArrayList and LinkedList are as follows:
1. ArrayList is a data structure based on dynamic array, while LinkedList is a data structure based on linked list;
2. For random access to get and set, ArrayList is better than LinkedList because LinkedList moves the pointer;
3. For add and remove operations, it is generally said that LinkedList is faster than ArrayList because ArrayList moves data.
However, the actual situation is not the case. LinkedList and ArrayList can not clearly explain who is fast and who is slow for adding or deleting, which will be analyzed in detail below.
Let's combine the source code analyzed before to see why it is like this:
The source code of random access, addition and deletion in ArrayList is as follows:
//Gets the element value at the index position public E get(int index) { rangeCheck(index); //First, judge whether the scope of index is legal return elementData(index); } //Set the value of the index position to element and return the original value public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; } //Add element to the specified location of ArrayList public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! //Copy the index and the data after the index to the position of index+1, that is, move one bit backward from the index System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; //Then insert element at index size++; } //Deletes the element at the location specified by ArrayList public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) //Move one bit to the left, and the original data in the index position has been overwritten System.arraycopy(elementData, index+1, elementData, index, numMoved); //Delete the last extra one elementData[--size] = null; // clear to let GC do its work return oldValue; } LinkedList The source code of random access, addition and deletion in is as follows: //Get the value of the index node public E get(int index) { checkElementIndex(index); return node(index).item; } //Set the value of the index element public E set(int index, E element) { checkElementIndex(index); Node<E> x = node(index); E oldVal = x.item; x.item = element; return oldVal; } //Add a new node before the index node public void add(int index, E element) { checkPositionIndex(index); if (index == size) linkLast(element); else linkBefore(element, node(index)); } //Delete the index node public E remove(int index) { checkElementIndex(index); return unlink(node(index)); } //Locate the node at index Node<E> node(int index) { // assert isElementIndex(index); //When index < size / 2, start from scratch if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { //When index > = size / 2, start from the end Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
It can be seen from the source code that when ArrayList wants to get(int index) elements, it directly returns the elements at the index position, and LinkedList needs to find them through the for loop. Although LinkedList has optimized the search method, for example, if index < size / 2, it starts from the left, otherwise it starts from the right, but the search is still slower than ArrayList. There is no doubt about this.
When ArrayList wants to insert or delete elements at the specified location, the main time-consuming is system The arraycopy action will move all elements behind the index;
The main time-consuming of LinkedList is to find the index through the for loop, and then insert or delete it directly. As a result, the two are not necessarily fast or slow. Here is a test program to test the insertion speed of the two:
import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; /* * @description Test the efficiency of ArrayList and LinkedList insertion * @eson_15 */ public class ArrayOrLinked { static List<Integer> array=new ArrayList<Integer>(); static List<Integer> linked=new LinkedList<Integer>(); public static void main(String[] args) { //First, insert 10000 pieces of data for both for(int i=0;i<10000;i++){ array.add(i); linked.add(i); } //Get the time of random access System.out.println("array time:"+getTime(array)); System.out.println("linked time:"+getTime(linked)); //Get the time when both insert data System.out.println("array insert time:"+insertTime(array)); System.out.println("linked insert time:"+insertTime(linked)); } public static long getTime(List<Integer> list){ long time=System.currentTimeMillis(); for(int i = 0; i < 10000; i++){ int index = Collections.binarySearch(list, list.get(i)); if(index != i){ System.out.println("ERROR!"); } } return System.currentTimeMillis()-time; } //insert data public static long insertTime(List<Integer> list){ /* * The amount of data inserted and the position inserted are the main aspects that determine their performance, * We can modify these two data to test their performance */ long num = 10000; //Indicates the amount of data to insert int index = 1000; //Indicates where to insert long time=System.currentTimeMillis(); for(int i = 1; i < num; i++){ list.add(index, i); } return System.currentTimeMillis()-time; } }
There are two main factors that determine their efficiency, the amount of data inserted and the location of the insertion. We can change these two factors in the program to test their efficiency.
When the amount of data is small and the test program is less than 30, the efficiency of the two is the same, and there is no significant difference;
When the amount of data is large, the efficiency of LinkedList is not as high as that of ArrayList when it starts at about 1 / 10 of the capacity. Especially when it is inserted in half and the second half, the efficiency of LinkedList is significantly lower than that of ArrayList, and the larger the amount of data, the more obvious.
For example, I tested a case where the running time of inserting 10000 data at the position of index=1000 (1 / 10 of the capacity), inserting 10000 data at the position of index=5000 and inserting 10000 data at the position of index=9000 are as follows:
Insert results in index=1000:
array time:4 linked time:240 array insert time:20 linked insert time:18
Insert the result at index=5000:
array time:4 linked time:229 array insert time:13 linked insert time:90
Insert the result at index=9000:
array time:4 linked time:237 array insert time:7 linked insert time:92
From the running results, the efficiency of LinkedList is getting worse and worse.
So when the amount of data inserted is very small, the difference between the two is not too big,
When the amount of data inserted is large, LinkedList will be better than ArrayList before about 1 / 10 of the capacity, and then worse than ArrayList, and the closer it is to the back, the worse it will be.
In my opinion, ArrayList is generally the first choice. Because LinkedList can realize data structures such as stack, queue and double ended queue, LinkedList can be used when specific needs arise.
Of course, when the amount of data is small, the two are almost the same. Choose to use them according to the specific situation;
When the amount of data is large, if you only need to insert or delete data in the front part, you can also choose LinkedList. On the contrary, choosing ArrayList is more efficient.
--------
Copyright notice: This article is the original article of CSDN blogger "Wuge chat programming", which follows the CC 4.0 BY-SA copyright agreement. Please attach the original source link and this notice for reprint.
Original link: https://blog.csdn.net/eson_15/article/details/51145788