Java面試中關于容器類List,Set是必問題目。但在我的面試經歷中很難遇到滿意的答復。大部分只能了解其大概使用方法,對其內部結構缺乏了解,錯誤的使用方式會導致性能大幅下降。
首先介紹ArrayList,顧名思義內部數據結構是數組
private transient Object[] elementData;
private int size;
public ArrayList(int initialCapacity){
}
在增加元素時,若容量不足進行擴充
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
新數組大小為之前數組大小*1.5+1 ,加上1保證oldCapacity為1的情況也能擴充為2
(類似分頁時總頁數=(總記錄數+ (每頁記錄數-1))/每頁記錄數算法)
刪除元素時通過 System.arraycopy把刪除位置后的所有元素前移一個位置實現
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; // Let gc do its work
return oldValue;
}
LinkedList大家都知道是通過鏈表實現,內部是一個雙向鏈表
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
private transient Entry<E> header = new Entry<E>(null, null, null);
private transient int size = 0;
}
private static class Entry<E> {
E element;
Entry<E> next;
Entry<E> previous;
}
插入和刪除都只要改動前后節點的next和previous實現
總結特點如下:
類型 | 內部結構 | 順序遍歷速度 | 隨機遍歷速度 | 追加代價 | 插入代價 | 刪除代價 | 占用內存 |
ArrayList | 數組 | 高 | 高 | 中 | 高 | 高 | 低 |
LinkedList | 雙向鏈表 | 高 | 低 | 低 | 低 | 低 | 中 |
所以:
- 一般順序遍歷情況下使用ArrayList,但注意構造函數中設置初始大小
- 盡量不對ArrayList進行插入或刪除操作(刪除尾部除外),若有多次刪除/插入操作又有隨機遍歷的需求,可以再構建一個ArrayList,把復合條件的對象放入新ArrayList,而不要頻繁操作原ArrayList
- 經常有刪除/插入操作而順序遍歷列表的情況下最適合使用LinkedList
已有 0 人發表留言,猛擊->>這里<<-參與討論
ITeye推薦