Turn from: https://www.cnblogs.com/sierrajuan/p/3639353.html
ArrayList and vectors use an array implementation, and you can assume that ArrayList or vectors encapsulate operations on an internal array, such as adding, deleting, inserting new elements, or extending and redirecting data to an array.
LinkedList uses a cyclic bidirectional linked list data structure. This is a different implementation technique than array-based ArrayList, which also determines that they will work in completely different scenarios.
The LinkedList list is connected by a series of table entries. A table entry always contains 3 parts: The element content, the precursor table, and the back-drive table, as shown in the figure:
The following illustration shows a connection between individual table entries for a linkedlist containing 3 elements. In the JDK implementation, whether or not likedlist is empty, there is a Header table entry inside the list that represents both the beginning of the linked list and the end of the linked list. The Back-drive table entry for the header of the table item is the first element in the list, and the predecessor of the header of the table item is the last element in the list.
The following is an example of adding and removing elements to compare the differences between ArrayList and LinkedList:
(1) Add elements to the end of the list:
The code to add elements to the end of the queue in ArrayList is as follows:
Public boolean Add (e) {
ensurecapacity (size+1);//Ensure that there is enough space in the internal array
elementdata[size++]=e;//Add the element to the end of the array and finish adding return
true;
The performance of the Add () method in ArrayList is determined by the ensurecapacity () method. The implementation of Ensurecapacity () is as follows:
Public VOD ensurecapacity (int mincapacity) {
modcount++;
int oldcapacity=elementdata.length;
if (mincapacity>oldcapacity) { //If the array capacity is insufficient, enlarge
object[] Olddata=elementdata;
int newcapacity= (oldcapacity*3)/2+1; 1.5 times times if
(newcapacitty<mincapacity) ///If the new capacity is less than the minimum required capacity, the minimum
//required capacity size is used
newcapacity= mincapacity; Array replication
elementdata=arrays.copyof (elementdata,newcapacity) for expansion;
As you can see, the Add () operation is highly efficient as long as the current capacity of the ArrayList is large enough. Expansion is required only when the ArrayList demand for capacity exceeds the current array size. During the expansion process, a large number of array copy operations will be performed. When an array is replicated, the System.arraycopy () method is eventually invoked, so the add () operation is quite efficient.
The LinkedList Add () operation is implemented as follows, and it also adds any element to the end of the queue:
Public boolean Add (e) {
addbefore (e,header);//add element to front of header return
true;
}
where the Addbefore () method is implemented as follows:
Private entry<e> Addbefore (E e,entry<e> Entry) {
entry<e> newentry = new Entry<e> (E,Entry, entry.previous);
Newentry.provious.next=newentry;
Newentry.next.previous=newentry;
size++;
modcount++;
return newentry;
}
Visible, Linkelist does not need to maintain the size of the capacity because of the structure of the linked list. At this point, it has a certain performance advantage over ArrayList, however, each increase in the element requires a new entry object and more assignment operations. In frequent system calls, performance can have a certain impact.
(2) Add elements to any location in the list
In addition to providing elements to the end of the list, the list interface provides a way to insert elements in any location: void Add (int index,e element);
Due to the different implementations, ArrayList and LinkedList have a certain performance difference in this method, because the ArrayList is based on an array, and the array is a contiguous memory space, if the element is inserted anywhere in the array, All elements that will necessarily result in this position need to be rearranged, so their efficiency is relatively low.
The following code is an implementation in ArrayList:
public void Add (int index,e element) {
if (index>size| | index<0)
throw new Indexoutofboundsexception (
"Index:" +index+ ", Size:" +size);
Ensurecapacity (size+1);
System.arraycopy (elementdata,index,elementdata,index+1,size-index);
Elementdata[index] = element;
size++;
}
You can see that an array copy occurs each time the insert operation. This operation does not exist when the element is added to the end of the list, and a large number of array recombination operations can result in low performance. And the more the insertion element is positioned in the list, the more expensive the array reorganization is.
And LinkedList shows the advantage at this point:
public void Add (int index,e element) {
Addbefore (element, Index==size?header:entry (index));
}
As you can see, for linkedlist, inserting data at the end of the list is the same as inserting data at any location, and will not degrade the way the insertion is due to the insertion position.
(3) Delete any position element
For deletion of elements, the list interface provides a way to delete elements at any location:
Public E-Remove (int index);
For ArrayList, the Remove () method and the Add () method are identical. After you remove an element from any location, you want to reorganize the array. The implementation of ArrayList is as follows:
Public E-Remove (int index) {
Rangecheck (index);
modcount++;
e oldvalue= (e) elementdata[index];
int nummoved=size-index-1;
if (nummoved>0)
system.arraycopy (elementdata,index+1,elementdata,index,nummoved);
Elementdata[--size]=null;
return oldValue;
}
You can see that the array is reorganized after each effective element deletion operation in ArrayList. And the more you delete the position, the more expensive the array will be when it is reorganized.
Public E-Remove (int index) {return
Remove (entry (index));
}
Private entry<e> Entry (int index) {
if (index<0 | | index>=size)
throw new Indexoutboundsexception (" Index: "+index+", Size: "+size";
entry<e> e= header;
if (index< (size>>1)) {//the element to be deleted is in the first half for
(int i=0;i<=index;i++)
e=e.next;
} else{for
(int i=size;i>index;i--)
e=e.previous;
}
return e;
}
In the LinkedList implementation, you first have to loop through the elements that you want to delete. If the location you want to delete is in the first half of the list, look backward, and then look forward if the position is in the second half. Therefore, it is very efficient to remove the elements that are either front or back, but the element to remove the middle of the list is almost half way through, and in the case where the list has a large number of elements, it is inefficient.
(4) Capacity parameters
Capacity parameters are unique performance parameters for array-based lists such as ArrayList and vectors. That represents the size of the initialized array. When the number of elements stored by ArrayList exceeds its existing size. The expansion of the array will result in a memory copy of the entire array. Therefore, a reasonable array size can help reduce the number of array expansion, thereby improving system performance.
Public ArrayList () {this
();
}
Public ArrayList (int initialcapacity) {
super ();
if (initialcapacity<0)
throw new IllegalArgumentException ("Illegal Capacity:" +initialcapacity)
This.elementdata=new object[initialcapacity];
}
ArrayList provides a constructor that can make the initial array size:
To construct a list with 1 million elements, for example, when the default initialization size is used, the relative time consumed is about 125ms, and when the array size is set to 1 million directly, the same ArrayList is only a relatively time-consuming 16ms.
(5) Traverse list
Traversal list operations are one of the most common list operations, with at least 3 of the commonly used list traversal methods after JDK1.5: A foreach operation, an iterator, and a for loop.
String tmp;
Long Start=system.currenttimemills (); ForEach for
(String s:list) {
tmp=s
}
System.out.println ("foreach Spend:" + (System.currenttimemills ()-start));
Start = System.currenttimemills ();
For (iterator<string> it=list.iterator (); It.hasnext ();) {
tmp=it.next ();
}
System.out.println ("iterator spend;") + (System.currenttimemills ()-start));
Start=system.currenttimemills ();
int size=;list.size ();
for (int i=0;i<size;i++) {
tmp=list.get (i);
}
System.out.println ("for spend;" + (System.currenttimemills ()-start));
Construct a ArrayList and equivalent LinkedList with 1 million data, and use the above code to test the relative duration of the test results as shown in the following table:
As you can see, the easiest foreach loop does not perform well, the overall performance is not as good as the average iterator, but the ArrayList table entry is good when you iterate through the list with random access for a for loop, but LinkedList's performance is unacceptable. There is no way to wait for the end of the program. This is because when random access is done to the LinkedList, the traversal of the list is always performed. Performance is very poor, should avoid use.