-
底层数据结构不同:ArrayList 使用动态数组实现,通过索引可以快速定位到元素。LinkedList 使用双向链表实现,每个节点都存储了元素本身以及指向前一个和后一个节点的指针,通过节点之间的指针关联来访问和操作元素。
-
插入和删除操作的效率不同:ArrayList 在尾部进行插入和删除操作时效率较高,因为不需要移动其他元素;但如果是在中间或开头插入、删除,就需要移动后面的所有元素,效率会比较低。LinkedList 在头部和尾部进行插入、删除操作时效率很高,只需要调整节点的指针即可;但如果是在中间位置操作,需要先从头或尾遍历链表找到目标位置,时间复杂度也是 O(n),不过找到位置后只需要调整指针,不需要像 ArrayList 那样移动大量元素,所以在某些特定场景下还是有优势的,而且 LinkedList 实现了 Deque 接口,还可以当作双端队列、栈来使用。
-
随机访问的效率不同:ArrayList 支持通过索引直接快速访问元素,时间复杂度为 O(1)。LinkedList 不支持随机访问,想要获取某个位置的元素,必须从头节点或尾节点开始逐个遍历,时间复杂度为 O(n)。
-
空间占用:ArrayList 在创建时会分配一段连续的内存空间,虽然会有一定的容量浪费(比如实际元素没装满数组),但只需要存储元素本身。LinkedList 每个节点除了存储元素,还需要额外存储两个指针(指向前一个和后一个节点),所以在存储相同数量元素的情况下,LinkedList 的空间占用通常会比 ArrayList 更大一些。
-
使用场景:ArrayList 更适合需要频繁随机访问元素,或者主要在尾部进行插入、删除操作的场景。LinkedList 更适合需要频繁在头部或尾部进行插入、删除操作,或者需要作为双端队列、栈使用的场景;如果是通过迭代器直接操作已知位置的节点,在中间插入、删除时也能发挥它调整指针快的优势。
-
线程安全:这两个集合都不是线程安全的,如果在多线程环境下使用,需要自己加锁保证线程安全,或者使用线程安全的 List 集合,比如 Vector、Collections.synchronizedList() 包装的 List,或者 CopyOnWriteArrayList。