Java中Array、List的区别
Array—是基于索引(index)的数据结构,它使⽤索引在数组中搜索和读取数据是很快的。Array获取数据的时间复杂度是O(1),但是要删除数据却是开销很⼤的,因为这需要重排数组中的所有数据。
List—是⼀个有序的集合,可以包含重复的元素,提供了按索引访问的⽅式,它实现了Collection接口。
List有两个重要的实现类:ArrayList和LinkedList
ArrayList:可以看作是能够⾃动增长容量的数组,利⽤ArrayList的toArray返回⼀个数组;Arrays.asList返回⼀个列表
ArrayList 和 LinkedList
数据结构: ArrayList底层使用Object[] elementData储存,默认长度为10;LinkedList:底层使用双向链表存储。
2、线程安全: ArrayList 和 LinkedList 都不考虑线程同步,不保证线程安全;
3、底层实现: 在底层实现上,ArrayList 是基于动态数组的,而 LinkedList 是基于双向链表的。事实上,它们很多特性的区别都是因为底层实现不同引起的。比如说:
在遍历速度上: 数组是一块连续内存空间,基于局部性原理能够更好地命中 CPU 缓存行,而链表是离散的内存空间对缓存行不友好;
在访问速度上: 数组是一块连续内存空间,支持 O(1) 时间复杂度随机访问,而链表需要 O(n) 时间复杂度查找元素;
在添加和删除操作上: 如果是在数组的末尾操作只需要 O(1) 时间复杂度,但在数组中间操作需要搬运元素,所以需要 O(n)时间复杂度,而链表的删除操作本身只是修改引用指向,只需要 O(1) 时间复杂度(如果考虑查询被删除节点的时间,复杂度分析上依然是 O(n),在工程分析上还是比数组快);
额外内存消耗上: ArrayList 在数组的尾部增加了闲置位置,而 LinkedList 在节点上增加了前驱和后继指针。
源码参考链接 https://cloud.tencent.com/developer/article/2197859
ArrayList 这么好用,可以完全替代数组吗?
大多数场景可以,但不能完全替代。
ArrayList 是基于 Object 数组封装的动态数组,我们不需要关心底层数组的数据搬运和扩容等逻辑,因此在大多数业务开发场景中,除非是为了最求极致的性能,否则直接使用 ArrayList 代替数组是更好的选择。
那么,ArrayList 有哪些地方上比数组差呢?
举例 1 - ArrayList 等容器类不支持 int 等基本数据类型,所以必然存在装箱拆箱操作;
举例 2 - ArrayList 默认的扩容逻辑是会扩大到原容量的 1.5 倍,在大数据量的场景中,这样的扩容逻辑是否多余,需要打上问题;
举例 3 - ArrayList 的灵活性不够。ArrayList 不允许底层数据有空洞,所有的有效数据都会 “压缩” 到底层数组的首部。因此,当需要基于数组二次开发容器时,ArrayList 并不是一个好选择。
例如,使用 ArrayList 开发栈的结构或许合适,可以在数组的尾部操作数据。但使用 ArrayList 开发队列就不合适,因为在数组的首部入队或出队需要搬运数据;
而数组没有这些约束,我们可以将数组设计为 “环形数组”,就可以避免入队和出队时搬运数据。例如 Java 的 ArrayBlockingQueue 和 ArrayDeque[2] 就是基于数组的队列。