1th Part List Summary
The frame chart of the list
The List is an interface that inherits from the collection interface. It represents an orderly queue.
Abstractlist is an abstract class that inherits from Abstractcollection. Abstractlist implements functions other than size (), get (int location) in the list interface.
Abstractsequentiallist is an abstract class that inherits from Abstractlist. Abstractsequentiallist implements "all the functions of the list, which manipulate the list according to the index value."
ArrayList, LinkedList, Vector, Stack is the list of 4 implementation classes.
ArrayList is an array queue, which is the equivalent of a dynamic array. It is implemented by array, with high random access efficiency, low random insertion and random deletion.
LinkedList is a two-way linked list. It can also be manipulated as a stack, a queue, or a two-terminal queue. LinkedList random access efficiency is low, but the efficiency of random insertion and random deletion is low.
Vectors are vector queues, and like ArrayList, it is also a dynamic array, implemented by arrays. But ArrayList is not thread-safe, and vector is thread-safe.
Stack is a stack, and it inherits from vectors. Its characteristics are: Advanced and Out (FILO).
2nd Part List Usage scenario
The ultimate goal of learning something is to be able to understand and use it. The following is a summary of the use of each list of scenarios, and then analyze the reasons behind.
If it involves "stack", "queue", "linked list" and other operations, should consider using list, the specific choice of which list, according to the following criteria to choose.
(01) for the need to quickly insert, delete elements, you should use LinkedList.
(02) for fast random access elements, you should use ArrayList.
(03)
For a single-threaded environment or multithreaded environment, but the list will only be manipulated by a single thread, you should use a class that is not synchronized, such as ArrayList.
For a multithreaded environment, and the list may be manipulated by multiple threads at the same time, you should use a synchronized class such as vector.
We verify the above (01) and (02) conclusions through the following test procedures. The reference code is as follows:
Copy Code code as follows:
Import java.util.*;
Import Java.lang.Class;
/*
* @desc contrast ArrayList and linkedlist insertion, random read efficiency, deletion efficiency
*
* @author Skywang
*/
public class Listcomparetest {
private static final int COUNT = 100000;
private static LinkedList LinkedList = new LinkedList ();
private static ArrayList ArrayList = new ArrayList ();
private static vector vector = new vector ();
private static Stack stack = new stack ();
public static void Main (string[] args) {
Line feed
System.out.println ();
Insert
Insertbyposition (stack);
Insertbyposition (vector);
Insertbyposition (LinkedList);
Insertbyposition (arrayList);
Line feed
System.out.println ();
Random Reads
Readbyposition (stack);
Readbyposition (vector);
Readbyposition (LinkedList);
Readbyposition (arrayList);
Line feed
System.out.println ();
Delete
Deletebyposition (stack);
Deletebyposition (vector);
Deletebyposition (LinkedList);
Deletebyposition (arrayList);
}
Get the name of the list
private static String Getlistname (List list) {
if (list instanceof LinkedList) {
return "LinkedList";
else if (list instanceof ArrayList) {
return "ArrayList";
else if (list instanceof Stack) {
return "Stack";
else if (list instanceof Vector) {
return "Vector";
} else {
return "List";
}
}
Inserts the count element into the list at the specified location and counts the time
private static void Insertbyposition (List list) {
Long starttime = System.currenttimemillis ();
Insert count number to position 0 to the list
for (int i=0; i<count; i++)
List.add (0, I);
Long endtime = System.currenttimemillis ();
Long interval = Endtime-starttime;
System.out.println (Getlistname (list) + ": Insert" +count+ "elements into the 1st position with time:" + interval+ "MS");
}
Deletes the count element from the specified location in the list and counts the time
private static void Deletebyposition (List list) {
Long starttime = System.currenttimemillis ();
Delete the first position element of the list
for (int i=0; i<count; i++)
List.remove (0);
Long endtime = System.currenttimemillis ();
Long interval = Endtime-starttime;
System.out.println (Getlistname (list) + ": delete" +count+ "elements from the 1st position use time:" + interval+ "MS");
}
According to position, constantly read the elements from the list and count the time
private static void Readbyposition (List list) {
Long starttime = System.currenttimemillis ();
Reading the list element
for (int i=0; i<count; i++)
List.get (i);
Long endtime = System.currenttimemillis ();
Long interval = Endtime-starttime;
System.out.println (Getlistname (list) + ": Read" +count+ "elements by position with time:" + interval+ "MS");
}
}
The results of the operation are as follows:
Stack:insert 100000 elements into the 1st position use time:1640 ms
Vector:insert 100000 elements into the 1st position use time:1607 ms
Linkedlist:insert 100000 elements into the 1st position use time:29 ms
Arraylist:insert 100000 elements into the 1st position use time:1617 ms
Stack:read 100000 elements by position use Time:9 ms
Vector:read 100000 elements by position use Time:6 ms
Linkedlist:read 100000 elements by position use time:10809 ms
Arraylist:read 100000 elements by position use Time:5 ms
Stack:delete 100000 elements from the 1st position use time:1916 ms
Vector:delete 100000 elements from the 1st position use time:1910 ms
Linkedlist:delete 100000 elements from the 1st position use time:15 ms
Arraylist:delete 100000 elements from the 1st position use time:1909 ms
From this, we can find:
Inserts 100,000 elements, LinkedList takes the shortest time: 29ms.
Delete 100,000 elements, LinkedList takes the shortest time: 15ms.
Traversing 100,000 elements, the LinkedList takes the longest time: 10809 MS, while ArrayList, stack, and vector are not much different and take only a few seconds.
Considering that the vector supports synchronization and that the stack is inherited from the vector, it concludes that:
(01) for the need to quickly insert, delete elements, you should use LinkedList.
(02) for fast random access elements, you should use ArrayList.
(03)
For a single-threaded environment or multithreaded environment, but the list will only be manipulated by a single thread, you should use a class that is not synchronized at this point.
Analysis of performance difference between LinkedList and ArrayList in the 3rd part
Let's take a look at why inserting elements in LinkedList is very fast, and ArrayList inserts are slow!
The code for inserting an element to a specified location in Linkedlist.java is as follows:
Copy Code code as follows:
Add a node before index, and the value of the node is element
public void Add (int index, E element) {
Addbefore (element, (index==size header:entry (index)));
}
Gets the node at the specified location in a two-way list
Private entry<e> Entry (int index) {
if (Index < 0 | | | index >= size)
throw new Indexoutofboundsexception ("Index:" +index+
", Size:" +size);
entry<e> E = header;
Gets the node at index.
If index < two-way linked list length 1/2, then look backward;
Otherwise, look forward from behind.
if (Index < (size >> 1)) {
for (int i = 0; I <= index; i++)
e = E.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}
Add the node (node data is e) before the entry node.
Private entry<e> Addbefore (e E, entry<e> Entry) {
Creates a new node newentry, inserts newentry before node E, and sets the newentry data to be E
entry<e> newentry = new Entry<e> (E, Entry, entry.previous);
Inserting newentry into a linked list
NewEntry.previous.next = Newentry;
newEntry.next.previous = Newentry;
size++;
modcount++;
return newentry;
}
From this we can see that the element is inserted into the LinkedList by the Add (int index, E element). First locate the index in the bidirectional list where you want to insert the node, and then insert a new node after you find it.
Two-way linked list to find the node of index position, there is an acceleration action: if the index < two-way list length of 1/2, then look backward; Otherwise, look forward from behind.
Next, let's look at the code in the Arraylist.java that inserts the element into the specified location. As follows:
Copy Code code as follows:
Add e to the specified location of the ArrayList
public void Add (int index, E element) {
if (Index > Size | | Index < 0)
throw New Indexoutofboundsexception (
"Index:" +index+ ", Size:" +size);
Ensurecapacity (size+1); Increments modcount!!
System.arraycopy (Elementdata, index, Elementdata, index + 1,
Size-index);
Elementdata[index] = element;
size++;
}
The role of Ensurecapacity (size+1) is "to confirm the ArrayList capacity, if not enough capacity, to increase capacity." ”
The real time-consuming operation is system.arraycopy (Elementdata, index, Elementdata, index + 1, size-index);
The arraycopy () declaration in the java/lang/system.java of the Sun JDK package is as follows:
public static native void Arraycopy (object src, int srcpos, object dest, int destpos, int length);
Arraycopy () is a JNI function that is implemented in the JVM. SUNJDK not see the source code, but can be seen in the OPENJDK package source. On-Line has the arraycopy () The analysis explanation, please refer to: system.arraycopy Source code Analysis
In fact, we only need to understand: System.arraycopy (elementdata, index, Elementdata, index + 1, size-index); All elements can be moved after index. This means that ArrayList's Add (int index, E Element) function will cause all elements to change after index!
With the above analysis, we can understand why inserting elements in LinkedList is very fast, and ArrayList is slow to insert elements.
The principle of "delete element" and "Insert Element" is similar, and there is no longer much explanation here.
Next, let's take a look at "Why random access in LinkedList is slow, and random access in ArrayList is fast."
Let's take a look at LinkedList randomly accessed code
Copy Code code as follows:
Returns the element at the specified position in LinkedList
Public E get (int index) {
Return Entry (index). element;
}
Gets the node at the specified location in a two-way list
Private entry<e> Entry (int index) {
if (Index < 0 | | | index >= size)
throw new Indexoutofboundsexception ("Index:" +index+
", Size:" +size);
entry<e> E = header;
Gets the node at index.
If the index < two-way linked list length of 1/2, then the previous search;
Otherwise, look forward from behind.
if (Index < (size >> 1)) {
for (int i = 0; I <= index; i++)
e = E.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}
From this we can see that the index element of LinkedList is obtained by getting (int index). First, find the element to index in a two-way list, and then return it after you find it.
Two-way linked list to find the node of index position, there is an acceleration action: if the index < two-way list length of 1/2, then look backward; Otherwise, look forward from behind.
Here's a look at ArrayList randomly accessed code
Copy Code code as follows:
Gets the element value of the index position
Public E get (int index) {
Rangecheck (index);
Return (E) Elementdata[index];
}
private void Rangecheck (int index) {
if (index >= size)
throw New Indexoutofboundsexception (
"Index:" +index+ ", Size:" +size);
}
From this we can see that the index element of ArrayList is obtained by getting (int index). Returns the elements of the index position directly in the array without needing to look like LinkedList.
The 3rd part vector and ArrayList comparison
In the same place
1, they're all list.
They all inherit from Abstractlist and implement the list interface.
The ArrayList and vector classes are defined as follows:
Copy Code code as follows:
Definition of ArrayList
public class Arraylist<e> extends abstractlist<e>
Implements List<e>, Randomaccess, cloneable, java.io.Serializable
The definition of vector
public class Vector<e> extends abstractlist<e>
Implements List<e>, Randomaccess, cloneable, java.io.Serializable {}
2 They all implement the randomaccess and Cloneable interfaces
Implementing randomaccess interfaces means that they all support fast random access;
Implementing the Cloneable interface means that they can clone themselves.
3 They are all implemented by arrays, which are essentially dynamic arrays
Arraylist.java defines array elementdata for saving elements
To save an array of data in ArrayList
Private transient object[] elementdata;
The Vector.java also defines an array elementdata for saving elements
To save an array of data in a vector
protected object[] Elementdata;
4 Their default array size is 10
If the capacity size is not specified when ArrayList or vectors are created, the default capacity size of 10 is used.
The default constructor for ArrayList is as follows:
Copy Code code as follows:
The ArrayList constructor. The default capacity is 10.
Public ArrayList () {
This (10);
}
The default constructor for the vector is as follows:
The Vector constructor. The default capacity is 10.
Public Vector () {
This (10);
}
5 They all support iterator and listiterator traversal
They all inherit from Abstractlist, and the Abstractlist iterator () interface returns iterator iterator and Listiterator () returns the Listiterator iterator respectively.
The difference
1 thread security is not the same
ArrayList is non thread safe;
The vector is thread-safe, and its functions are synchronized, that is, it supports synchronization.
ArrayList applies to single-threaded, and vectors apply to multithreading.
2 different for serialization support
ArrayList supports serialization, which is not supported by vectors, that is, ArrayList has an implementation java.io.Serializable interface and the vector does not implement the interface.
3 The number of constructors is different
The ArrayList has 3 constructors, and the vector has 4 constructors. Vector in addition to including 3 constructors similar to ArrayList, another constructor can specify the capacity increase factor.
The ArrayList constructor is as follows:
Copy Code code as follows:
Default constructor
ArrayList ()
Capacity is the default capacity size for ArrayList. When the capacity is insufficient due to increased data, the capacity adds half of the last capacity size.
ArrayList (int capacity)
Create a ArrayList that contains collection
ArrayList (collection< extends e> Collection)
The vector constructor is as follows:
Default constructor
Vector ()
The capacity is the default capacity size of the vector. When the capacity increases due to increased data, the capacity is increased by one times per volume.
Vector (int capacity)
Create a vector that contains collection
Vector (collection< extends e> Collection)
The capacity is the default capacity size of the vector, and capacityincrement is the increment for each vector capacity increase.
Vector (int capacity, int capacityincrement)
4 Capacity Increase mode different
When adding elements individually, "new capacity" = "(Original capacity x3)/2 + 1" If ArrayList capacity is insufficient.
While the capacity growth of vectors is related to the "growth coefficient", if "growth coefficient" is specified and the "growth coefficient is valid (that is, greater than 0)", then "new capacity" = "raw capacity + growth factor" each time the capacity is insufficient. If the growth factor is invalid (that is, less than/equal to 0), then "new capacity" = "raw capacity x 2".
The main functions of capacity growth in ArrayList are as follows:
Copy Code code as follows:
public void ensurecapacity (int mincapacity) {
To "Modify statistics" +1
modcount++;
int oldcapacity = Elementdata.length;
If the current capacity is insufficient to accommodate the current number of elements, set the new capacity = "(Original capacity x3)/2 + 1"
if (Mincapacity > Oldcapacity) {
Object olddata[] = elementdata;
int newcapacity = (oldcapacity * 3)/2 + 1;
if (Newcapacity < mincapacity)
newcapacity = mincapacity;
Elementdata = arrays.copyof (Elementdata, newcapacity);
}
}
The main functions of capacity growth in vectors are as follows:
Copy Code code as follows:
private void Ensurecapacityhelper (int mincapacity) {
int oldcapacity = Elementdata.length;
Increase capacity when vector capacity is insufficient to accommodate all current elements.
If the capacity increment coefficient is >0 (ie capacityincrement>0), the capacity is increased when capacityincrement
Otherwise, the capacity is increased by one fold.
if (Mincapacity > Oldcapacity) {
object[] OldData = elementdata;
int newcapacity = (capacityincrement > 0)?
(Oldcapacity + capacityincrement): (oldcapacity * 2);
if (Newcapacity < mincapacity) {
newcapacity = mincapacity;
}
Elementdata = arrays.copyof (Elementdata, newcapacity);
}
}
5 support for enumeration is different. Vector supports traversal through enumeration, and list does not support
The code that implements enumeration in the vector is as follows:
Copy Code code as follows:
Public enumeration<e> elements () {
Implementing enumeration with Anonymous classes
return new enumeration<e> () {
int count = 0;
Whether the next element exists
public boolean hasmoreelements () {
return count < Elementcount;
}
Get Next element
Public E nextelement () {
Synchronized (vector.this) {
if (Count < Elementcount) {
Return (E) elementdata[count++];
}
}
throw new Nosuchelementexception ("Vector enumeration");
}
};
}