你真的了解ArrayList和LinkedList吗

面试经常被问到ArrayList和LinkedList的区别,当然,这时候大部分人都是背书一样脱口而出:

ArrayList适合查询,不适合增删改。

LinkedList适合增删改,不适合查询。

其实,深入了解过的人会发现,这个答案太片面了。

片面的原因在于对ArrayList的底层原理了解的不深入,当然我这篇文章写得也不会特别特别深入,只是起到知识引导的作用。

ArrayList是一个被修饰了的数组,它的内部持有了一个数组,用来存放真正的数据。

到了这里就需要了解一下ArrayList是怎么扩容的。为什么,因为扩容对它的性能花销特别大。

补充一点,需要关注,1.扩容 2.索引遍历

1.扩容

   ArrayList:合适的初始化数组长度能大大的减少扩容的系统花销,因为不需要在每次扩容的时候,都把所有的数据重新copy到新的,足够长度的新数组(ArrayList在计算机内容中的结构是连续的,他底层的扩容实现就是这么写的)

思考一下,LinkedList增删改为什么比ArrayList快,就是因为他的数据结构特别,一个节点包含上一个和下一个的地址,在特定的地方插入新的节点,只需要将其前后的节点拆分重组即可,不需要像ArrayList一样,需要将整个后面的数组全部后移一位。

2.索引遍历

   了解了扩容,那么我们来谈另外一个问题,  查询, ArrayList的查找是从header开始逐个遍历(但是要注意,因为是内存连续的空间,所以这个查找很快),LinkedList的查找可以从header开始,也可以从ender开始,一个一个地址的查找,(因为内存不是连续的,所以计算机磁头拿到地址数据的时候需要一个个转到这些地址去查询)。

总结一下:

ArrayList查询很快,因为内存连续,但是增删改很慢,因为需要将变动的整数据后移(删改)或者整个整个数组的内容copy到新数组(增)。

LinkedList查询很慢,因为内存不连续,查找地址是件耗时的事情,但是增删改很快,因为只需要改动一个节点的上下游节点节即可。

解决缺点:

了解了上面那些,我们就可以按照具体的业务场景对他们进行优化了。

比如,我们将ArrayList的数组初始化到合适的,足够的长度,免去了copy的过程,是不是就算是优化了一些。

比如,当长度足够的时候(不考虑整个copy的情况),我们在ArrayList越靠近尾部的地方进行指定位置的插入,然后只会发生少部分数组的后移或者前进,是不是就算是很大的优化了。

相对应的LinkedList,假设每次新增的节点都在整个链条的中间部分,那么当链条足够长,这个查询将会消耗大部分时间。

一个最优的情况对应一个最差的情况,这时候ArrayList的增删改就比LinkedList好很多

具体是怎么样的,参考一下的文章:

https://www.jianshu.com/p/5b3aa50aa388

写给自己的总结,以免忘记:

ArrayList的扩容是将原数组copy到新的长度的数组里面!!!

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章