浅谈LinkedList

LinkedList简介

LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。 

LinkedList 实现 List 接口,能对它进行队列操作。

LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。

LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。

LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。

LinkedList 是非同步的。

LinkedList相对于ArrayList来说,是可以快速添加,删除元素,ArrayList添加删除元素的话需移动数组元素,可能还需要考虑到扩容数组长度。

LinkedList继承体系

 

 

LinkedList源码分析

属性

 

LinkedList本身的属性比较少,主要有三个,一个是size,表名当前有多少个节点;一个是first代表第一个节点;一个是last代表最后一个节点。

 

构造方法

  • 无参构造

默认构造方法是空的,什么都没做,表示初始化的时候size为0,first和last的节点都为空:

  • 带Collection集合的构造

执行逻辑:

1、使用this()调用默认的无参构造函数。

2、调用addAll()方法,传入当前的节点个数size,此时size为0,并将collection对象传递进去

3、检查index有没有数组越界的嫌疑

4、将collection转换成数组对象a

5、循环遍历a数组,然后将a数组里面的元素创建成拥有前后连接的节点,然后一个个按照顺序连起来。

6、修改当前的节点个数size的值

7、操作次数modCount自增1.

源码如下:

addAll方法:

add方法

  • add(E e)方法

 

实际上就是调用在尾部添加元素的方法

 

 

 

 

 

 

 

 

  • add(int index,E element )方法

指定位置往数组链表中添加元素

1、检查添加的位置index 有没有小于等于当前的长度链表size,并且要求大于0

2、如果是index是等于size,那么直接往链表的最后面添加元素,相当于调用add(E e)方法

3、如果index不等于size,则先是索引到处于index位置的元素,然后在index的位置前面添加新增的元素。

get方法

 

  • getFirst方法

返回第一个节点元素

  • getLast方法

返回最后一个结点元素

remove方法

  • remove()方法

remove()方法本质是调用removeFirst方法,删除第一个结点

  • remove(int index)方法

删除指定位置的结点。先是检查移除的位置是否在链表长度的范围内,如果不在则抛出异常,根据索引index获取需要移除的节点,将移除的节点置空,让其上一个节点和下一个节点对接起来。

 

unlink方法:

 

  • remove(Object o)方法

删除链表中的指定结点

 

  • removeFirst()方法

移除链表中的第一个结点。将第一个节点置空,让下一个节点变成第一个节点,链表长度减1,修改次数加1,返回移除的第一个节点。

 

  • removeLast()方法

移除最后一个节点,将最后一个节点置空,最后一个节点的上一个节点变成last节点,,链表长度减1,修改次数加1,返回移除的最后一个节点。

 

set方法

set方法不修改modCount值。

clear方法

将所有链表元素置空,然后将链表长度修改成0,修改次数加1

toArray方法

创建一个Object的数组对象,然后将所有的节点都添加到Object对象中,返回Object数组对象。

listIterator方法

这个方法返回的是一个内部类ListIterator,用户可以使用这个内部类变量当前的链表元素,但是由于LinkedList也是非线程安全的类,所以和ArrayList中的 Iterator一样,多线程下面使用,也可能会产生多线程修改的异常。

 

小结

LinkedList 是双向列表。

  • 链表批量增加,是靠for循环遍历原数组,依次执行插入节点操作。对比ArrayList是通过System.arraycopy完成批量增加的。增加一定会修改modCount。
  • 通过下标获取某个node 的时候,(add select),会根据index处于前半段还是后半段 进行一个折半,以提升查询效率
  • 删也一定会修改modCount。 按下标删,也是先根据index找到Node,然后去链表上unlink掉这个Node。 按元素删,会先去遍历链表寻找是否有该Node,如果有,去链表上unlink掉这个Node。
  • 改也是先根据index找到Node,然后替换值。改不修改modCount。
  • 查本身就是根据index找到Node。
  • 所以它的CRUD操作里,都涉及到根据index去找到Node的操作。

 

 

 

 

 

 

 

 

 

 

全部评论

相关推荐

昨天 12:06
已编辑
华侨大学 测试开发
最近看到很多 92 的,甚至是硕士,开始往测开赛道卷,说实话有点看不懂。先把话说清楚,大厂里的测开,绝大多数时间干的还是测试的活,只是写点自动化脚本、维护测试平台、接接流水线,真正像开发一样做系统、做架构、做核心平台的测开少得可怜,基本都集中在核心提效组,而且人很少,外面进去的大概率轮不到你,我想真正干过人都清楚。很多人被洗脑了,以为测开也是开,和后端差不多,只是更简单、更轻松、还高薪。现实情况是,测开和开发的职业路径完全不一样。开发的核心是业务和系统能力,测开的核心是稳定性和覆盖率,前者是往上走,后者天花板非常明显。你可以见到很多开发转测开,但你很少见到干了几年测开还能顺利转回开发的。更现实一点说,92 的高学历如果拿来做测开,大部分时间就是在做重复性很强的杂活,这种工作对个人能力的放大效应非常弱。三年下来,你和一个双非的,甚至本科的测开差距不会太大,但你和同龄的后端、平台开发差距会非常明显。这不是努不努力的问题,是赛道问题。所谓测开简单高薪,本质上是把极少数核心测开的上限,当成了整个岗位的常态来宣传。那些工资高、技术强的测开,本身就是开发水平,只是挂了个测开的名。普通人进去,99% 做的都是项目兜底型工作,而不是你想象中的平台开发。测开不是不能做,但它绝对不是开发的平替,也不是性价比最优解。如果你是真的不想做开发,追求稳定,那测开没问题。但如果你只是觉得测开比后端容易,还能进大厂,那我劝你冷静一点,这只是在用短期安全感换长期天花板。有92的学历,如果你连测开这些重复性工作都能心甘情愿接受,那你把时间精力用在真正的开发、系统、业务深度上,回报大概率比卷测开要高得多。想清楚再下场,别被岗位名和话术带偏了,就算去个前端客户端也是随便占坑的,测开是一个坑位很少赛道,反而大面积学历下放,不用想也能知道会是什么结果,我想各位在JAVA那里已经看到了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务