数组、ArrayList和链表的那些事
数组
数组存储特点
- 必须指定初始化大小,方能分配存储空间
- 数据连续存储
- 获取具体的元素(根据索引下标返回数据)时效率比较高
- 插入或删除元素时性能差
数组删除元素
这里我们以删除索引为5的元素为例:
当删除索引为5的元素时,其后所有的元素都需要向前移位;如果删除的是索引为0的元素,那整个数组要移位的元素个数是N-1,从性能上讲就是O(N);当然如果删除数组尾部的元素,那数组的元素是不需要移位的,从性能上讲是O(1)
数组插入元素
这里我们以在索引5和6之间插入元素为例:
插入新的元素和删除元素类似,当在索引为6处插入新的元素时,其后所有的元素都需要向后移位(忽略扩容);
如果在索引为0处插入新的元素,那整个数组要移位的元素个数是N,从性能上讲就是O(N);当然如果在数组的尾
部插入新的元素,那数组的元素是不需要移位的,从性能上讲就是O(1)
ArrayList底层就是基于数组实现的,所以以上的各种情况同样适用于ArrayList
链表
简单来讲,链表的诞生就是为了解决连续存储的诸多缺点,所以链表有以下特点:
- 由一系列不连续的节点组成,数据节点在内存中不必相连
- 插入新元素或删除元素,原有元素不需要移位,避免了插入和删除移位带来的线性开销
单链表
链表分为单链表和双链表,我们先来看下单链表:
这时候如果需要删除元素,只需要将该节点的链接关系重新设置即可,并不需要移动元素:
插入新的元素和删除类型,只需要改变链接关系即可:
接下来我们看下双链表
双链表
双链表是相对于单链表来说的,在单链表中,当前元素只和下一个元素链接,所以单链表中只能获取next
(下一个)节点,并不能获取previous
(上一个)节点,但在双链表是都可以获取的。
删除的情况和单链表类似:
插入新元素也和单链表类似
总结
总结来说,对于基于数组实现的容器,因为数据存储是连续,所以可以在获取具体元素时,性能比基于链表实现的容器要好;但是在删除和插入新元素方面,基于链表实现的容器,表现更好