ArrayList和LinkedList的区别

发布于:2025-04-15 ⋅ 阅读:(26) ⋅ 点赞:(0)

ArrayList和LinkedList的区别

ArrayList 和 LinkedList 都是 Java 中常用的列表类,它们都实现了 List 接口,但是在底层数据结构、性能表现和使用场景上有一些关键的区别:

1. 底层数据结构
  • ArrayList:底层是基于动态数组实现的。在插入或删除元素时,可能需要移动其他元素来保持数组的顺序。
  • LinkedList:底层是基于双向链表实现的,每个元素包含对前后元素的引用,可以在常数时间内插入和删除元素。
2. 查询性能
  • ArrayList:由于底层是数组,查询(通过索引访问元素)是非常高效的,时间复杂度是 O(1)。
  • LinkedList:查询元素时需要从头或者尾遍历链表,时间复杂度是 O(n)。
3. 插入和删除性能
  • ArrayList:在数组的末尾添加元素是 O(1) 的操作,但在中间或头部插入或删除元素时需要移动其他元素,时间复杂度为 O(n)。
  • LinkedList:在链表的头部或尾部插入或删除元素是 O(1) 的操作,但如果需要在中间插入或删除元素,仍然需要遍历到指定位置,时间复杂度为 O(n)。
4. 内存占用
  • ArrayList:由于是基于数组实现,内存占用较为紧凑,只存储元素本身。
  • LinkedList:每个元素除了存储数据外,还需要存储前后节点的引用,因此内存开销较大。
5. 扩容
  • ArrayList:当数组容量不够时,ArrayList 会进行扩容,通常是将数组容量扩展为原来的 1.5 倍或 2 倍。这意味着可能需要在扩容时进行数据的拷贝,影响性能。
  • LinkedList:不会出现扩容问题,因为它是基于链表实现的,每次插入一个元素只需要创建一个新的节点。
6. 线程安全

ArrayList 和 LinkedList:都不是线程安全的。如果需要线程安全的列表,可以使用 CopyOnWriteArrayList 或者手动同步代码块。

7. ArrayList和LinkedList通俗易懂的例子
ArrayList 比喻:从下到上的积木塔

假设你有一个 积木塔,每一块积木都整齐地堆叠在一起,从下到上,每块积木的顺序都很明确。

  • 顺序排列: 积木塔的每一块积木都有固定的顺序,位置是固定的。你可以很容易地查看每块积木的编号(或位置),就像 ArrayList 中的元素按顺序排列,每个元素都有一个固定的索引,可以快速通过索引来找到想要的元素。
  • 快速访问: 如果你想要查询某块积木的位置,比如第三块,你可以直接看到它,像是通过索引查找数组中的元素一样,很方便。
  • 插入和删除: 如果你想要在积木塔中间插入一块新的积木,或者拿走某块积木,就会影响到其他所有积木。比如,如果你在中间插入一块新的积木,必须把后面的积木都往上挪动一个位置;如果删除某块积木,后面的积木要向下移动。这就像 ArrayList 在中间插入或删除元素时需要移动后续的元素,导致操作的效率下降。
  • 小结:
    ArrayList 就像一个从下到上搭建好的积木塔,元素按顺序排列,访问方便,但插入或删除中间的元素时,需要移动后面的元素,效率较低。

这个比喻更能形象地反映 ArrayList 中顺序性和访问便捷性,同时也能清楚地说明在进行插入或删除操作时的低效性,尤其是当操作发生在中间时。

LinkedList 比喻:自行车的链条

想象一下自行车的链条,每一个链环都连接在一起,形成一个循环的结构。每个链环代表链表中的一个元素,而链环与链环之间的连接就是元素之间的引用或链接。

  • 按顺序连接: 就像自行车的链条,每个链环通过链接串联在一起,每个元素都知道下一个链环的位置,但它们并不需要按顺序存放在相邻的内存位置。链条的每个链环都有一个指向下一个链环的链接(类似 LinkedList 中的节点指向下一个节点)。
  • 动态插入与删除: 如果你想在链条中间插入一个新的链环(类似在 LinkedList 中插入一个元素),你只需要调整相邻链环的连接方向,前后的链环不需要移动,只需要修改指向即可。比起插入或删除 ArrayList 中的元素,LinkedList 的操作要高效得多,因为它不需要移动大量的元素。
  • 查找元素: 然而,如果你想要查找某个特定位置的链环,就不那么方便了。你必须从第一个链环开始,逐一遍历链条,直到找到你想要的链环。这就像在 LinkedList 中查找元素,必须按顺序访问每个节点,无法直接通过索引进行快速访问。
  • 小结:
    LinkedList 就像一个由链环构成的自行车链条,每个链环知道下一个链环的位置,插入和删除操作高效,但查找元素需要遍历整个链条,无法像 ArrayList 那样快速通过索引访问。

这个比喻很好地展示了 LinkedList 的特点:动态插入与删除 的高效性,以及顺序查找 的低效性。链条中的每个链环就像链表中的一个节点,它们通过指针连接在一起,但访问时却需要逐个遍历。

总结
  • ArrayList 适用于查找频繁、插入和删除不太频繁的场景。
  • LinkedList 适用于插入和删除频繁的场景,尤其是在链表的头部或尾部进行操作时。
    选择哪一个主要取决于你的应用场景和性能要求。

网站公告

今日签到

点亮在社区的每一天
去签到