c语言编程笔录

首页 >   > 笔记大全

笔记大全

ArrayList和LinkedList的区别、扩容机制及底层的实现方式是什么

更新时间:2023-07-19

ArrayList和LinkedList的区别

ArrayList和LinkedList都是Java集合框架中的List接口的实现类,它们有各自的优缺点和适用场景。

ArrayList是基于动态数组实现的,它的内部使用数组来保存数据,数组的容量可以动态增长。LinkedList是基于双向链表实现的,它的内部使用链表保存数据。由于两种数据结构的不同,在性能、内存消耗和使用场景上有一些区别。

首先,ArrayList的读取和修改元素的速度较快,因为它能够根据索引直接访问元素。而LinkedList的插入和删除元素的速度较快,因为它只需要改变前后节点的指向即可。

其次,ArrayList的内存消耗较小,因为它只需要存储元素本身以及一些额外的元数据,而LinkedList需要额外的存储指针来维护链表结构。

扩容机制

ArrayList的扩容机制是在数组元素不足以容纳新元素时,会创建一个新的更大的数组,并将原数组中的元素复制到新数组中。默认情况下,每次扩容都会将数组的容量增加50%。

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

LinkedList的扩容机制是在插入元素时不需要额外的扩容操作,因为链表的容量是动态的。每次插入新元素时,只需要创建一个新的节点,并将其添加到链表中即可。

底层实现方式

ArrayList的底层使用数组来保存元素,定义了一个Object类型的数组变量elementData来存放元素,可以通过索引直接访问数组中的元素。ArrayList还提供了一些方法(如add、remove等)来方便地操作数组。在插入或删除元素时,需要移动数组中的部分元素。

private Object[] elementData;
public E get(int index) {
    rangeCheck(index);
    return elementData(index);
}

LinkedList的底层使用双向链表来保存元素,定义了一个Node节点类作为链表的节点类型。每个节点包含前向指针prev、后向指针next和存储的元素值。LinkedList通过头节点和尾节点来维护链表的头尾。在插入或删除元素时,只需要改变节点的指针即可。LinkedList还提供了一些方法(如add、remove等)来方便地操作链表。

private static class Node {
    E item;
    Node next;
    Node prev;
    Node(Node prev, E element, Node next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

总结

ArrayList和LinkedList都是常用的Java集合类,各自适用于不同的场景。ArrayList适合读取和修改元素的操作,LinkedList适合插入和删除元素的操作。ArrayList底层使用数组保存数据,在数据量较大时可以减少内存消耗,但在插入和删除元素时性能较差。LinkedList底层使用链表保存数据,在插入和删除元素时性能较好,但在读取和修改元素时性能较差。根据具体的应用场景和需求,选择合适的集合类可以提高程序的性能和效率。