博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java 集合 2 - LinkedList
阅读量:5876 次
发布时间:2019-06-19

本文共 3715 字,大约阅读时间需要 12 分钟。

java 集合 2 - LinkedList

参考文章:

LinkedList是基于实现的。

特性
是否存取null值 可以
元素是否可以重复 可以
是否有序 有序
是否线程安全 不安全

接下来直接通过源码(jdk1.8)分析。

结点定义

private static class Node
{ E item; Node
next; Node
prev; Node(Node
prev, E element, Node
next) { this.item = element; this.next = next; this.prev = prev; } }复制代码

可见,对于每一个结点,可以通过prev找到它的直接前驱,通过next找到其后继。

头,尾结点

/**     * Pointer to first node.     * Invariant: (first == null && last == null) ||     *            (first.prev == null && first.item != null)     */    transient Node
first; /** * Pointer to last node. * Invariant: (first == null && last == null) || * (last.next == null && last.item != null) */ transient Node
last;复制代码

作为双向链表,链表头的前驱为链表尾,链表尾的后继为链表头,first和last满足如下关系: first不为空,且链表尾为空,那么链表只有一个元素,保存于链表头;last不为空,且链表头为空,那么链表只有一个元素,保存于链表尾。

add方法

public boolean add(E e) {        linkLast(e);        return true;    }        public void add(int index, E element) {        checkPositionIndex(index);        if (index == size)            linkLast(element);        else            linkBefore(element, node(index));    }复制代码
  • 一个参数的add方法实际调用了linkLast方法,linkLast方法。
  • 两个参数的add方法先检查下标是否越界,之后如果下标(从0开始)为当前链表的长度(size从1开始),那么就是新增元素于链表尾,否则调用linkbefore插入元素。

linkLast方法

/**     * Links e as last element.     */    void linkLast(E e) {        final Node
l = last; final Node
newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; }复制代码

可见linkLast方法会将新的结点进行构造,然后替换原来的尾结点,如果原来的尾结点为空,那意味着链表还没有元素(有一个元素时头尾就都不为null),此时构造的就是第一个元素,使头尾都指向同一元素(该元素的前驱和后继都为null),如果原来的尾结点已经存在,那么将原来的尾结点的后继指向新的尾结点即可。

linkBefore方法

/**     * Inserts element e before non-null Node succ.     */    void linkBefore(E e, Node
succ) { // assert succ != null; final Node
pred = succ.prev; final Node
newNode = new Node<>(pred, e, succ); succ.prev = newNode; if (pred == null) first = newNode; else pred.next = newNode; size++; modCount++; }复制代码

这里对应succ参数的定位发生在node方法中:

node方法

/**     * Returns the (non-null) Node at the specified element index.     */    Node
node(int index) { // assert isElementIndex(index); if (index < (size >> 1)) { Node
x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node
x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }复制代码

结合上面双参数的add方法,可见该方法首先会判断新插入的点在链表中的大体位置(前一半还是后一半),然后从前往后或从后往前定位到指定下标的点并返回。

再回头看linkBefore方法,构建新节点,修改被插入结点的前驱,被插入结点的原前驱的后继。

get方法

public E get(int index) {        checkElementIndex(index);        return node(index).item;    }复制代码

get方法首先会检查下标,然后通过node方法定位目标结点,取出值返回。

indexOf方法

public int indexOf(Object o) {        int index = 0;        if (o == null) {            for (Node
x = first; x != null; x = x.next) { if (x.item == null) return index; index++; } } else { for (Node
x = first; x != null; x = x.next) { if (o.equals(x.item)) return index; index++; } } return -1; }复制代码

该方法用于查找指定元素的下标,可见该方法会对目标元素是否为null采用不同的搜索方式,没找到则返回-1。


---END---

转载地址:http://yjkix.baihongyu.com/

你可能感兴趣的文章
无锡启用汽车电子标识卡,为市民带来便捷生活
查看>>
SSLyze:开源SSL安全监控工具
查看>>
国际保险公司面向家庭和个人推出网络安全保险业务
查看>>
迪普科技亮相2016全国环境信息技术与应用交流大会
查看>>
常用线缆用量计算公式大汇总
查看>>
云服务器 ECS 配置:利用MySQL读写分离,提升应用数据吞吐性能
查看>>
如何做到“恰好一次”地传递数十亿条消息
查看>>
从Objective-C到Swift,你必须会的(二)组合options
查看>>
C#动态编译计算表达式的值
查看>>
ping baidu.com 发包不通
查看>>
硬盘IO,SAS,SATA,和HD TUNE
查看>>
最佳实践:如何基于MNS实现一对多拉取消息消费模型
查看>>
快速阅读《POSTFIX权威指南》
查看>>
PhalGo-Respones
查看>>
[MySQL 源码] MySQL drop table(压缩表)效率与流程分析
查看>>
activiti自定义流程之整合(六):获取我的申请任务
查看>>
高效Linux bash快捷键及alias总结
查看>>
css知识
查看>>
Struts 框架 之 Hello World
查看>>
【系统】如何控制cpu资源使用
查看>>