Java ArrayList与LinkedList 源码浅析

60 阅读1分钟

Java ArrayList与LinkedList 源码浅析

首先我们先来看看ArrayList

image.png ArrayList继承了AbstractList抽象类;实现了Serializable,Cloneable,RandomAccess接口

首先看几个成员变量

  • private static final int DEFAULT_CAPACITY = 10; 默认初始值大小,为10
  • private static final Object[] EMPTY_ELEMENTDATA = {};
  • private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMPTYDATA = {}
  • transient Object[] elementData; 存放元素的数组
  • private int size; 元素的数量

构造方法

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

new ArrayList<E>()不指定大小时,使用默认大小空数组初始化

public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

add(e)

会先调用ensureCapacitvInternal(size+1) 保证有足够的容量去新增一个元素 在ensureCapacitvInternal(size+1)中先调用calculateCapacity(minCapacity)获取最小的minCapcacity,如果ementData==DEFAULTCAPACITY_EMPTY_ELEMPTYDATA 就返回DEFAULT_CAPACITY,其余情况返回传入的minCapacity(size+1); 在调用ensureExplicitCapacity(minCapacity)会确保在minCapacity > ementData的条件下调用grow(minCapacity)扩容,在任何条件下都会modCount++;

ArrayList的扩容机制

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    // 每次扩容原容量的1.5
    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);
}

newCapcacityoldCapacity的1.5倍

  1. 若newCapacity < minCapacity,newCapacity就被赋值为oldCapacity
  2. 若newCapacity > MAX_ARRAY_SIZE,就调用hugeCapacity在hugeCapacity中 minCapacity < 0 就抛出OOM,其他情况返回 minCapacity > MAX_ARRAY_SIZE? Integer.MAX_VALUE:MAX_ARRAY_SIZE
  3. 调用Arrays.copy()将扩容后的数组赋值给ementData.

add(e,idx)

  • 先rangeCheckForAdd()判断index > size
  • 还是调用ensureCapacityInternal modCount++
  • 调用System.arraycopy(),size++

LinkedList

Node类

```java
public static Class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;
    
    public Node<E>(Node<E> prev,E e,Node<E> next){
        this.item = e;
        this.next = next;
        this.prev = prev;
}




add(e)

public boolean add(E e) {
    linkLast(e);
    return true;
}

void linkFirst(E e) {
    final Node<E> f = first;
    final Node<E> newNode = new Node<>(null,e,f);
    if (last == null) {
        last = newNode;
    } else {
        f.prev = newNode;
    }
    size++;
    modeCount++;
}
    

void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l,e,null);
    if (l == null) {
        first = newNode;
    } else {
        l.next = newNode;
    }
    size++;
    modCount++;
}