一.为什么要使用LinkedList
1.ArrayList有个明显的缺点,就是当容量接近满值的时候,需要进行扩容,扩容的过程还需要生成新的集合,把原来的数组数据拷贝到新的数组里,这就造成了极大的内存浪费。但是使用链表结构的LinkedList就不一样了,需要多少就申请多少
2.LinkedList因为采用双链表结构,增删效率大于ArrayList。
二.什么是链表数据结构
LinkedList 使用的是双向链表 每个元素你可以认为是一个节点,这个节点有三个属性,一个是元素,一个是上个节点的地址,一个是下个节点的地址。
补充:单链表就很好理解了,就是只有下个节点的地址,没有上个节点的地址
如图:直观感受双链表
看完上面的链表图就很容易发现为什么链表增删效率高了。
一:高效的增删
1.remove
remove()方法两个版本,一个是根据指定元素删除匹配相等的第一个元素remove(Object o),另一个是删除指定下标处的元素remove(int index)
看源码remove(Object o)是需要找到o对应的Node,remove(int index)只需要判断index是否存在,就可以直接删除,删除后其他所有元素位置不用发生改变,只需要修改上个Node和下个Node的数据即可。
2.add
add()方法也有两个版本,一个add(E e),该方法在LinkedList的末尾插入元素,因为有last指向链表末尾,在末尾插入元素的花费是常数时间,只需简单修改几个相关引用即可;另外一个add(int index,E e),该方法是在指定下标出插入元素,需要通过线性查找找到具体位置,然后修改相关引用完成插入操作。
总结:不管是添加还是删除数据,都只需要修改相邻的数据前驱和后继即可,不需要改变其他数据,这就是链表增删的高效的原因。
二:低效的查找
链表的缺点就是查找的效率低于ArrayList ,无法向 ArrayList 那样随机访问指定位置的元素,LinkedList 查找过程要稍麻烦一些,需要从链表头结点(或尾节点)向后查找,时间复杂度为 O(N)查询效率相对ArrayList 低点,尤其是中间下标的数据要便利所有数据的1/2次。
三:LinkedList 队列特性
add() 会在容量不够时抛出异常:IllegalStateException; offer()则不会,只返回false
element() 会在没元素时抛出异常:NoSuchElementException; peek()返回null;
remove() 会在没元素时抛出异常:NoSuchElementException; poll()返回null;
offer() 将指定的元素插入此队列(如果立即可行且不会违反容量限制),此方法通常要优于 add(E)
通常使用offer(),peek(),poll()方法进行操作,可以避免异常,符合队列的数据结构并且方便队列使用。
总结:
1.如果需求有频繁的增删数据使用LinkedList
2.如果需要储存队列使用LinkedList ,LinkedList 获取第一个元素和最后一个元素效率高,元素使用完移除队列对效率高。(之前笔者做过直播软件,需要顺序播放用户赠送的礼物,使用LinkedList 储存礼物列表就是很不错的选择)