从源码对比ArrayList和LinkList区别

先列下提纲:

  1. ArrayList和LinkList底层的数据结构不一样
  2. 对于set()和get()方法, ArrayList比LinkList要快,也就是说,使用ArrayList查询比LinkList快
  3. 对于add() 和remove()方法,LinkList比ArrayList要快,增删方面使用LinkList更好
  4. 对于使用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 next, Entry 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 = 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,暂更

你可能感兴趣的:(Java,Java基础重温,集合重温)