Java集合

77 阅读2分钟

ArrayList和LinkedList的区别?

两者都实现了 List接口,两者都是线程不安全的(Vector是线程安全的)

区别:

  • 底层数据结构不同
    • ArrayList使用动态数组实现,通过索引进行快速访问元素
    • LinkedList使用双向链表实现,通过节点之间的指针,进行元素的访问和操作
  • 插入和删除操作的效率不同
    • ArrayList在尾部的插入和删除操作效率较高,但在中间或开头的插入和删除效率较低,需要移动元素
    • LinkedList在任意位置的插入和删除操作效率都比较高,因为只需要调整节点之间的指针,但是LinkedList是不支持随机访问的,所以除了头节点外,插入和删除的时间复杂度都是0(n),效率也不是很高,所以LinkedList基本没人用
  • 随机访问效率不同
    • ArrayList支持通过索引进行快速随机访问,时间复杂度为O(1)
    • LinkedList需要从头或尾开始遍历链表,时间复杂度为O(n)
  • 空间占用
    • ArrayList在创建时需要分配一段连续的内存空间,因此会占用较大的空间
    • LinkedList每个节点只需要存储元素和指针,因此相对较小
  • 使用场景
    • ArrayList适用于频繁随机访问和尾部的插入删除操作
    • LinkedList适用于频繁的中间插入删除操作和不需要随机访问的场景

ArrayList扩容机制说一下?

ArrayList在添加元素时,如果当前元素的个数达到了内部数组的容量上限,就会触发扩容操作

ArrayList扩容操作的主要内容:

  • 计算新的容量:一般情况,新的容量会扩大为原来的1.5倍,然后检查是否超过了最大容量限制
    int newCapacity = ArraysSupport.newLength(oldCapacity,
        minCapacity - oldCapacity, /* 最小增长 */
        oldCapacity >> 1           /* 首选增长 */);
  • 创建新的数组:根据得到的容量,创建一个更大的新数组
  • 将元素复制:将原来数组中的元素逐个复制到新数组中
  • 更新引用:将ArrayList内部指向原数组的引用指向新数组
  • 完成扩容:扩容完成后,可以继续添加新元素