list集合原始碼分析
阿新 • • 發佈:2019-02-07
List集合我們眾所周知的就是有序可重複,底層是一維陣列,但是我現在通過面試的情況發現自己對於集合的理解還是太淺薄了。
ArrayList 底層是一個數組,讓我們瞭解ArrayList到底是什麼。
首先ArrayList都知道查詢快,增刪慢,瞭解一下為什麼?
看一下原始碼:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
可以知道ArrayList中實現了RandomAccess這個介面,追蹤一下:
public interface RandomAccess {
}
what?實現是介面是空的?那怎麼回事?原來是這樣啊!
既然我們知道他是在集合中,那麼我就順著他的父類尋找,先看一下List,沒有發現,List在向上是collection,這時我們看看他的方法:
@SuppressWarnings({"rawtypes", "unchecked"}) public static void shuffle(List<?> list, Random rnd) { int size = list.size(); if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) { for (int i=size; i>1; i--) swap(list, i-1, rnd.nextInt(i)); } else { Object arr[] = list.toArray(); // Shuffle array for (int i=size; i>1; i--) swap(arr, i-1, rnd.nextInt(i)); // Dump array back into list // instead of using a raw type here, it's possible to capture // the wildcard but it will require a call to a supplementary // private method ListIterator it = list.listIterator(); for (int i=0; i<arr.length; i++) { it.next(); it.set(arr[i]); } } }
private static void swap(Object[] arr, int i, int j) {
Object tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public class Collections
這樣就特別清晰了!原始碼其實就是一個for迴圈!
ArrayList中初始長度為10,陣列擴容1.5倍+1
private static final int DEFAULT_CAPACITY = 10;
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);//右移一位除以2
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);
}
缺點是向指定的索引位置插入物件或刪除物件的速度較慢.因為指向索引位置插入物件時,會將指定索引位置及之後的所有物件相應向後移動一位Vector集合與ArrayList集合沒有本質區別,因為Vector中方法和ArrayList的方法是一致的,但是每個方法上都有synchronized
關鍵字,所以說Vector集合是執行緒安全,但是也正因為如此,vector更浪費資源。
LinkList底層是一個雙向連結串列,查詢慢,插入刪除快。
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++;
}
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
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++;
}
每次查詢都要從頭或尾進行遍歷
public int lastIndexOf(Object o) {
int index = size;
if (o == null) {
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (x.item == null)
return index;
}
} else {
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (o.equals(x.item))
return index;
}
}
return -1;
}
public int indexOf(Object o) {
int index = 0;
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}
就這樣吧!!!!