先列下提纲:
开始逐条分析:
一. 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 next, Entry previous) {
this.element = element;
this.next = next;
this.previous = previous;
}
}
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 = entry(index);
E oldVal = e.element;
e.element = element;
checkElementIndex(index);
Node 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 entry(int index) {//从这个方法,可以看出,set 与get都需要每次利用二分法从前往后或者从后往前循环查找. 第二点
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
Entry 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 addBefore(E e, Entry entry) {
Entry newEntry = new Entry(e, entry, entry.previous);//此处描述,链表集合的add就是直接增加一个Entry,然后改变相应的指针 第三点
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}
private E remove(Entry 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,暂更