简介:ArrayList和LinkedList都是List接口的实现类。允许出现重复的元素,元素有序,即存入顺序和取出顺序一致。
1、线程安全性:ArrayList和LinkedList都是不同步的,不保证线程安全
2、底层数据结构:
(1)ArrayList集合底层采用的是Object数组结构。
(2)LinkedList底层采用的是双向链表结构(jdk7之前为循环链表,jdk7取消了循环)。
3、插入和删除:
(1)如果容量为 n 的ArrayList在数组中的指定位置 i 插入一个元素,则原数组的i元素以及(n-i)个元素都需要进行移位。所以时间复杂度是O(n-i)。元素越多,增删速度越慢。
(2)LinkedList因为是双链表结构,插入和删除只需要更改元素之间的引用关系即可,增删的速度跟元素的多少无关。时间复杂度近似O(1)。
4、查询:ArrayList支持高效快速随机访问,通过元素序号快速查询获取元素。而LinkedList不支持快速访问,即查询慢。
5、内存空间占用:ArrayList的空间浪费主要是因为需要在列表的结尾预留一定的容量空间,而LinkedList的空间花费主要体现在每个元素的存储需要更大的空间(要存放每个元素的前驱引用和后继引用)。
拓展
RandomAccess接口:RandomAccess 接口中好像并没有定义什么,只是一个标识,标识实现这个接口的类具有随机访问功能。 如ArrayList就实现了RandomAccess 接口。
遍历方式选择:
(1)实现了RandomAccess 接口,优先选择for循环遍历,其次是foreach。
(2)未实现RandomAccess 接口,优先选择迭代器Iterator遍历(foreach底层也是通过Iterator实现的)。大SIZE数据千万千万不能使用for循环遍历。
原因:
LinkedList中的get()的源码
如果用for循环遍历LinkedList,在get第i个元素需要先到get第(i-1)个元素,等于在拿任意一个位置的元素都需要把前面的数据走一遍。等于for循环内嵌套了一个for循环,数据非常大时,时间复杂度近似于O(N*N)。而时间的复杂度大小顺序为O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n)。因此切忌不能用for循环来比遍历LinkedList数组。
ArrayList中的get()的源码
ArrayList是直接从数组中里拿一个位置上的元素,时间复杂度是O(1),是非常快的。