ArrayList 和 LinkedList


一、ArrayList

1.ArrayList的默认初始化容量

 private static final int DEFAULT_CAPACITY = 10;

这个也可以在创建一个对象时自己指定:

ArrayList<Object> list=new ArrayList<>(12);

2.ArrayList底层使用数组维护

transient Object[] elementData;

3.扩容机制

private void grow(int minCapacity) {    //minCapacity:扩容后最小需要容量
    // overflow-conscious code
    int oldCapacity = elementData.length;   //旧容量
    int newCapacity = oldCapacity + (oldCapacity >> 1); //新容量为1.5倍旧容量
    if (newCapacity - minCapacity < 0) //新容量 小于 最小需要容量
        newCapacity = minCapacity;     //就把新容量提到minCapacity(最小需要容量)
    
    // 如果新容量大于 MAX_ARRAY_SIZE,进入(执行) `hugeCapacity()` 方法来比较 minCapacity和MAX_ARRAY_SIZE
    //如果minCapacity大于最大容量,则新容量则为`Integer.MAX_VALUE`,
    //否则,新容量大小则为 MAX_ARRAY_SIZE 即为 `Integer.MAX_VALUE - 8`。
    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);
}
//定义了 MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    //对minCapacity和MAX_ARRAY_SIZE进行比较
    //若minCapacity大,将Integer.MAX_VALUE作为新数组的大小
    //若MAX_ARRAY_SIZE大,将MAX_ARRAY_SIZE作为新数组的大小
    //MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

4.重写了sort()方法

public void sort(Comparator<? super E> c) {
    final int expectedModCount = modCount;
    Arrays.sort((E[]) elementData, 0, size, c);//底层调用的还是Arrays.sort()
    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
    modCount++;
}

二、LinkedList

1.LinkedList底层由 双向链表 维护

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}
transient int size = 0;		//记录数组长度
transient Node<E> first;	//头指针
transient Node<E> last;		//尾指针

2.头插法与尾插法

//头插法
private void linkFirst(E e) {
    final Node<E> f = first;
    final Node<E> newNode = new Node<>(null, e, f);
    first = newNode;
    if (f == null)
        last = newNode;
    else
        f.prev = newNode;
    size++;
    modCount++;
}

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

3. LinkedList的add()方法默认采用尾插法

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

三、两者的比较

1.ArrayList 是基于数组的,所以它使用索引在数组中搜索和读取数据是很快的O(1);但是要插入、删除数据却是开销很大的,因为这需要移动数组中插入位置之后的的所有元素O(n)。

2.LinkedList是基于双向链表的,它的随机访问集合元素时性能较差,因为需要在双向列表中找到要index的位置O(n);但在插入,删除操作是更快的O(1)。

3.LinkedList需要更多的内存,因为ArrayList的每个索引的位置是实际的数据,而LinkedList中的每个节点中还需要存储前后节点的索引。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值