首先問的是ArrayList和LinkedList的區(qū)別。
先看ArrayList的相關(guān)源碼:
private static final int DEFAULT_CAPACITY = 10;
transient Object[] elementData;
可以看出ArrayList底層是實現(xiàn)了一個Object數(shù)組,并且初始容量為10
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動態(tài)擴(kuò)容是原本的1.5倍,而且擴(kuò)容是把原本的數(shù)據(jù)復(fù)制到新的數(shù)組,這樣很耗費時間,所以一般在建arraylist的時候,可以把數(shù)據(jù)長度定義為預(yù)想的1.5倍,這樣就可以免去擴(kuò)容導(dǎo)致的復(fù)制問題
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
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);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
在看ArrayList的插入和刪除,都需要移動后面的元素,比較耗時
再看LinkedList的代碼
public boolean add(E e) {
linkLast(e);
return true;
}
public void add(int index, E element) {
checkPositionIndex(index);
if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
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;
}
可以看到LinkedList的插入和刪除其實也是需要通過for循環(huán)查找到具體位置的,所以并不一定比ArrayList的刪除插入快。
再看HashMap的源碼
這題答得比較爛,其實是了解的,我們先來看源碼
DEFAULT_INITIAL_CAPACITY =16 默認(rèn)容量為
MAXIMUM_CAPACITY =1 << 30 最大容量為
DEFAULT_LOAD_FACTOR = 0.75f 默認(rèn)負(fù)載因子
TREEIFY_THRESHOLD=8 鏈表轉(zhuǎn)換紅黑樹的閥值
UNTREEIFY_THRESHOLD=6 紅黑樹轉(zhuǎn)換鏈表的閥值
MIN_TREEIFY_CAPACITY=64 桶中bin最小hash容量,如果大于這個值會進(jìn)行
總結(jié):
- 一個是數(shù)組實現(xiàn),一個是鏈表實現(xiàn)。
- ArrayList可以快速查詢,鏈表需要遍歷。ArrayList插入刪除需要移動元素,鏈表只需要改變節(jié)點指向就行
- ArrayList內(nèi)存不足時需要動態(tài)擴(kuò)容,每次是原來的1.5倍,LinkedList不需要動態(tài)擴(kuò)容
- 這一題回答的時候,動態(tài)擴(kuò)容以及插入刪除的效率沒有說出來