ArrayList 和 LinkList 的區別
ArrayList 的相關知識
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
由上面源碼可知,Arraylist繼承自AbstractList 實現了List ,Cloneable,Serializable,RandomAccess接口.其中Cloneable是克隆接口,Serializable是實現序列化操作的接口,便於對象的傳輸。而今天重點要描述一下這個RandomAccess。
RandomAccess接口是一個標記接口,實現了它的list集合支持隨機訪問,目的是是算法在隨機和隨機訪問時顯得更靈活。在collections的 binarySearch源碼如下
public static <T>
int binarySearch(List<? extends Comparable<? super T>> list, T key) {
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
return Collections.indexedBinarySearch(list, key);
else
return Collections.iteratorBinarySearch(list, key);
}
我們可以看到,他首先會判斷這個list是否實現了RandomAccess接口,如果這個條件和list.size()<BINARYSEARCH_THRESHOLD(其中: BINARYSEARCH_THRESHOLD Collections的一個常量(5000),它是二分查找的閥值。)滿足其中任何一個則使用Collections的indexedBinarySearch(list,key)方法。否則會調用Collections.iteratorBinarySearch(list,key)方法。
這兩者的代碼實現分別如下:
indexedBinarySearch 方法:
- private static <T>
- int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
- int low = 0;
- int high = list.size()-1;
- while (low <= high) {
- int mid = (low + high) >>> 1;
- Comparable<? super T> midVal = list.get(mid);
- int cmp = midVal.compareTo(key);
- if (cmp < 0)
- low = mid + 1;
- else if (cmp > 0)
- high = mid - 1;
- else
- return mid; // key found
- }
- return -(low + 1); // key not found
- }
indexedBinarySearch 方法是直接通過get來訪問元素
iteratorBinarySearch方法
- private static <T>
- int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)
- {
- int low = 0;
- int high = list.size()-1;
- ListIterator<? extends Comparable<? super T>> i = list.listIterator();
- while (low <= high) {
- int mid = (low + high) >>> 1;
- Comparable<? super T> midVal = get(i, mid);
- int cmp = midVal.compareTo(key);
- if (cmp < 0)
- low = mid + 1;
- else if (cmp > 0)
- high = mid - 1;
- else
- return mid; // key found
- }
- return -(low + 1); // key not found
- }
iteratorBinarySearch中ListIterator來查找相應的元素
在javadoc中指出人們認識到隨機存取和順序存取之間的區別通常是模糊的。例如,一些列表實現提供了漸進的線性訪問時間,如果它們在實踐中獲得了巨大的、但持續的訪問時間。這種接口通常應該實現這個接口。根據經驗,列表實現應該實現這個接口,如果對於類的典型實例,這個循環:
for (int i=0, n=list.size(); i < n; i++)
list.get(i);
runs faster than this loop:
for (Iterator i=list.iterator(); i.hasNext(); ) i.next();
也就是說實現RandomAccess接口的的List可以通過簡單的for循環來訪問數據比使用iterator訪問來的高效快速。
回過頭來,我們再說說ArrayList,
{
private static final long serialVersionUID = 8683452581122892189L;
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer.
*/
private transient Object[] elementData; //ArrayList的底層是一個基數組。
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @exception IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this(10); //默認的初始大小為10.
}
public void ensureCapacity(int minCapacity) { //給定所需的最小容量
modCount++;
int oldCapacity = elementData.length; //原來數組中的元素大小
if (minCapacity > oldCapacity) {//如果所需的最小容量大於 原數組中數據的個數時。
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1; //則要對舊的數組進行擴容,新數組的容量為原來的1.5倍+1
if (newCapacity < minCapacity)//如果新的容量還是小於最小需求的容量,則將最小需求容量賦給新容量。
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);//在將就數組中的元素拷貝到新的容量數組中
}
}
LinkedList 的相關知識
public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable
public LinkedList() {
header.next = header.previous = header;
}
它的增添方法常用的是add(),刪除常用的方法是remove(),它的底層是一個雙向鏈表。
對於隨機訪問get和set,ArrayList覺得優於LinkedList,因為LinkedList要移動指針。
對於增添與刪除add和remove,ArrayList需要挪動數據,除非是在數組末尾,需要消耗一定的時間,而LinkedList便可以很輕易地做到。
總結ArrayList 和LinkedList的區別:
1.兩者繼承的基類不一樣。ArrayList 繼承自AbstractList,而LinkedList繼承自 AbstractSequentialList。
2.底層結構不一樣。ArrayList 采用的是動態數組,而LinkedList采用的是雙向鏈表。
3.ArrayList實現了RandomAccess接口,所以在隨機訪問時效率比較高。而LinkedList需要不停地移動指針。
4.對於增添與刪除add和remove,ArrayList需要挪動數據,除非是在數組末尾,需要消耗一定的時間,而LinkedList便可以很輕易地做到。
5。ArrayList 默認初始容量是10,擴容時擴容它舊容量的1.5倍加1.
ArrayList 和 LinkList 的區別