ArrayList和LinkedList是Java中常用的列表实现。它们在内部数据结构和性能特点上有明显的区别。
从代码以及性能上比较ArrayList和LinkedList:
内部数据结构:
- ArrayList使用数组作为底层数据结构,通过索引来访问和操作元素。这使得随机访问非常高效,但在插入和删除操作时需要移动后续元素。
- LinkedList使用双向链表作为底层数据结构,每个节点包含元素和指向前一个和后一个节点的引用。这使得插入和删除操作高效,但随机访问需要遍历链表。
插入和删除操作:
- ArrayList在末尾插入和删除元素时效率高,因为只需要调整数组的大小和修改元素的值。但在中间插入和删除时,需要移动后续元素,效率较低。
- LinkedList在任意位置插入和删除元素时效率高,因为只需要修改节点的指针。但随机访问元素时效率较低,因为需要遍历链表。
随机访问和迭代操作:
- ArrayList支持快速的随机访问,通过索引即可直接访问元素。适用于需要频繁访问元素的场景。
- LinkedList适用于需要频繁插入和删除元素,以及迭代操作的场景。通过遍历节点的指针,可以高效地进行迭代操作。
内存占用:
- ArrayList在一开始就分配了一块连续的内存空间,大小随着元素的增长而动态调整。这可能导致内存浪费,尤其在元素数量不确定或变化较大时。
- LinkedList不需要连续的内存空间,每个节点只包含元素和指针,因此可以根据需要动态分配内存。这可能在内存占用方面更加灵活。
从时间角度来比较ArrayList和LinkedList:
随机访问:
ArrayList通过索引直接访问元素,时间复杂度为O(1),因为它使用了基于数组的数据结构。而LinkedList需要遍历链表来查找元素,时间复杂度为O(n),其中n是链表的长度。因此,在需要频繁进行随机访问的场景下,ArrayList更为高效。
插入和删除操作:
ArrayList在末尾插入和删除元素的时间复杂度为O(1),因为它只需要调整数组的大小和修改元素的值。然而,在中间插入和删除时,由于需要移动后续元素,时间复杂度为O(n)。相比之下,LinkedList在任意位置的插入和删除操作都只需要修改节点的指针,时间复杂度为O(1)。因此,在频繁进行插入和删除操作的场景下,LinkedList更为高效。
从底层代码出发来了解ArrayList和LinkedList:
ArrayList和LinkedList是Java中常用的列表实现,它们在底层的代码实现上有明显的区别。
ArrayList的底层实现:
- ArrayList使用一个数组来存储元素。在初始化时,会创建一个具有初始容量的数组。如果添加的元素数量超过了数组的当前容量,ArrayList会进行扩容操作。扩容时,会创建一个新的更大容量的数组,并将旧数组中的元素复制到新数组中。默认情况下,扩容的大小是原容量的1.5倍,这有助于减少频繁的扩容操作。
- 在随机访问时,ArrayList可以通过索引直接访问数组中的元素,因为数组的元素在内存中是连续存储的。这使得ArrayList在获取元素、修改元素和删除末尾元素时的时间复杂度都为O(1)。
- 然而,在中间插入和删除元素时,需要将插入点后的元素向后移动或删除点后的元素向前移动,以保持数组的连续性。这个移动操作的时间复杂度为O(n),其中n是数组的长度。因此,在插入和删除大量元素的情况下,ArrayList的性能可能较差。
LinkedList的底层实现:
- LinkedList使用双向链表作为底层数据结构。每个节点都包含一个元素和两个指针,一个指向前一个节点,一个指向后一个节点。在初始化时,会创建一个空链表。
- 在插入和删除元素时,LinkedList只需要修改节点的指针即可,不需要像ArrayList那样移动元素。这使得插入和删除操作的时间复杂度为O(1)。由于链表的特性,它可以在任何位置高效地插入和删除元素。
- 然而,在随机访问时,LinkedList需要从头节点开始遍历链表,直到找到目标位置的节点。这导致随机访问的时间复杂度为O(n),其中n是链表的长度。
总结:
ArrayList通过数组实现,在随机访问上效率高,但在插入和删除操作中可能需要移动元素。LinkedList通过链表实现,在插入和删除操作上效率高,但随机访问较慢。
TOP补充:
在之前的文章中,我对ArrayList和LinkList进行了简单的压力测试,顺序写入和删除一百万数据,随机插入五万的数据,感兴趣的小伙伴可以去看一下!
Java中ArrayList和LinkList的区别,Java数据结构性能比较:ArrayList vs LinkedList,不懂?看我就够了_国服梦想家的博客-CSDN博客