ArrayList VS LinkedList:
ArrayList和LinkedList是Java中常用的两种集合类,虽然它们都实现了List接口,但在内部实现和性能方面有以下区别:
内部实现:
ArrayList是基于数组实现的动态数组
,它可以自动扩容和缩容。
LinkedList是基于双向链表实现的
,每个节点都包含了当前元素的值以及指向前一个节点和后一个节点的引用。
访问和修改元素的效率:
ArrayList支持随机访问,可以通过索引直接访问和修改元素,因此在随机访问和修改元素时效率较高,时间复杂度为O(1)。但在插入和删除元素时,需要移动其他元素,时间复杂度为O(n)`。它通过索引来访问和操作元素。
对于ArrayList来说,当为尾部插入时,直接通过下标检索到最后一个位置将元素插入即可,但当为头部插入时,过程如下所示:
LinkedList不支持随机访问
,需要从头节点开始遍历链表才能访问和修改元素
,时间复杂度为O(n)
。但在插入和删除元素时,只需要修改节点的引用,时间复杂度为O(1)
。
内存占用:
ArrayList在内存中连续存储元素
,可以利用CPU缓存,局部性原理,因此占用的内存空间相对较小。
引入CPU缓存
,可以缩短时间,当第一次读写某些数据时,将其写在CPU缓存中,等再次使用该数据时,就不需要重新从内存中访问了
局部性原理:
当我们将某些数据放入CPU缓存中时,不应该只放单独的某一个数据,而应该将与它相邻的一些数据都读入,因为该数据访问后,很大机率接下来要访问的就是与它相邻的元素
但局部性原理只能适用于数组,而不能适用于链表,原因如下:
那么为什么LinkedList占用内存空间大呢?
原因:每一个元素都有两个指针,一个用于指向下一个元素,一个用于指向上一个元素,少量的数据也许并不会体现出内存占用上的缺点,但当数据非常多时,指针累计占用的内存空间就会非常大
至于选择ArrayList还是LinkedList取决于对于随机访问和修改元素的需求以及对于插入和删除元素的频繁程度。如果需要频繁进行随机访问和修改元素操作,可以选择ArrayList;如果需要频繁进行插入和删除元素操作,可以选择LinkedList。但在实际开发中,我们都是使用ArrayList,一方面是由于实际开发中很少出现要将元素插入头部或者尾部的这种情况,另一方面是由于ArrayList的各个方面的性能都要优于LinkedList
解析二者源码:
点击ArrayList的源码:
点击LinkedList的源码:
ArrayList相比于LinkedList实现了RandomAccess接口
,那么接口到底有什么作用呢?
我们点开该接口的源码,如下所示: