先列下提綱:
- ArrayList和LinkList底層的數據結構不一樣
- 對於set()和get()方法, ArrayList比LinkList要快,也就是說,使用ArrayList查詢比LinkList快
- 對於add() 和remove()方法,LinkList比ArrayList要快,增刪方面使用LinkList更好
- 對於使用Iterator,暫更
開始逐條分析:
一. ArrayList和LinkList底層的數據結構不一樣
(1)ArrayList
private static final Object[] EMPTY_ELEMENTDATA = {};
private transient Object[] elementData;
private int size;
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;//這個無參很好的解釋了數組集合的由來 第一點
}
(2)LinkList
Entry 可以當作節點類 ,它有三個成員變量 previous上一個節點 ,next下一個節點, element節點的值 .previous和next可以當作是指針
private static class Entry {
E element;
Entry next;
Entry previous;
Entry(E element, Entry<E> next, Entry<E> previous) {
this.element = element;
this.next = next;
this.previous = previous;
}
}
- private transient Entry header = new Entry(null, null, null);
- private transient int size = 0;
public LinkedList() { -
}header.next = header.previous = header; //這個無參構造,很好的解釋了雙向循環列表的名字由來 第一點
二. 對於set()和get()方法, ArrayList比LinkList要快,也就是說,使用ArrayList查詢比LinkList快
(1)ArrayList
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();//這處地方很好的解釋了爲何,ArrayList一上來的時候不能直接set,因爲本來就是空數組,還有條件判斷,所以一開始應該要add 第二點
checkForComodification();
try {
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;//此處表明了,set真的就是找到下標後放進去 第二點
return oldValue;
}
public E get(int index) {
rangeCheck(index);
return elementData(index);//get時就是從數組中把下表傳進去取
}
(2)LinkList
public E set(int index, E element) {
Entry<E> e = entry(index);
E oldVal = e.element;
e.element = element;
checkElementIndex(index);
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
}
public E get(int index) {
return entry(index).element;
checkElementIndex(index);
return node(index).item;
}
private Entry<E> entry(int index) {//從這個方法,可以看出,set 與get都需要每次利用二分法從前往後或者從後往前循環查找. 第二點
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
Entry<E> e = header;
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() 和remove()方法,LinkList比ArrayList要快,增刪方面使用LinkList更好
(1)ArrayList
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
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);
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);//此處說明,ArrayList的add就是重新生成(copy)一個數組,先擴容,然後賦值 第三點
}
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);//此處說明AyyayList的remove就是重新生成一個長度短的數組 第四點
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
(2)LinkList
public boolean add(E e) {
addBefore(e, header);
return true;
}
private Entry<E> addBefore(E e, Entry<E> entry) {
Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);//此處描述,鏈表集合的add就是直接增加一個Entry,然後改變相應的指針 第三點
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}
private E remove(Entry<E> e) {
if (e == header)
throw new NoSuchElementException();
E result = e.element;//從這往下的一段邏輯,可以看出,LinkList集合的remove就是把當前的節點前後節點的指針改變,同時清空自身的指針和元素 第四點
e.previous.next = e.next;
e.next.previous = e.previous;
e.next = e.previous = null;
e.element = null;
size--;
modCount++;
return result;
}
四 對於使用Iterator,暫更