博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LinkedList源码分析
阅读量:7056 次
发布时间:2019-06-28

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

成员变量

transient int size = 0;//元素个数transient Node
first;//第一个元素transient Node
last;//最后一个元素

存储单元

arrayList实际上是一个双向列表,每个元素节点都持有前、后元素节点的引用

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; } }

新增

public boolean add(E e) {        linkLast(e);        return true;    }    public void addFirst(E e) {        linkFirst(e);    }    public void addLast(E e) {        linkLast(e);    }    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++; } private void linkFirst(E e) { final Node
f = first; final Node
newNode = new Node<>(null, e, f); first = newNode; if (f == null) last = newNode; else f.prev = newNode; size++; modCount++; }

可以往链表前面添加,也可以往后添加,默认往后添加。

创建一个新节点,前置元素为当前的last,后置元素为空,把这个节点设置为last节点,并把之前的last节点的后置节点设置为这个节点。

 

查询

public E get(int index) {        checkElementIndex(index);        return node(index).item;    }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; } }

不像ArrayList可以通过下标直接找到元素,LinkedList必须从第一个节点开始,每到下一个节点计数+1,直到当前的下标。

 

删除

一 、普通删除

public E remove() {        return removeFirst();    }    public E removeFirst() {        final Node
f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); } private E unlinkFirst(Node
f) { // assert f == first && f != null; final E element = f.item; final Node
next = f.next; f.item = null; f.next = null; // help GC first = next; if (next == null) last = null; else next.prev = null; size--; modCount++; return element; }

增加的逆过程,把链子解开

二 、删除对象

public boolean remove(Object o) {        if (o == null) {            for (Node
x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); return true; } } } else { for (Node
x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); return true; } } } return false; }

若对象为空,则删除第一个为空的元素,不为空则删除这个元素,然后解开链子

三 、删除指定下标

public E remove(int index) {        checkElementIndex(index);        return unlink(node(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; } }

这里稍微有点意思,如果下标比元素数据的一半小,从头开始向后遍历,否则从尾部开始向前遍历

 

插入元素

public void add(int index, E element) {        checkPositionIndex(index);        if (index == size)            linkLast(element);        else            linkBefore(element, node(index));    }    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++; } 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; } }

首先获取指定下标节点(从后遍历/从前遍历),然后修改这个节点的前置节点,指向新节点

 

转载于:https://www.cnblogs.com/jiaqirumeng/p/9063866.html

你可能感兴趣的文章
python的学习笔记之——time模块常用内置函数
查看>>
计算机是如何工作的
查看>>
【c++】必须在类初始化列表中初始化的几种情况
查看>>
阿拉伯数字1与英语字母l造成的代码bug
查看>>
深度学习常见的专业术语
查看>>
2018-2019-2 20165334《网络对抗技术》Exp2 后门原理与实践
查看>>
HTML提交方式post和get区别(实验)
查看>>
Java 11.do语句
查看>>
学习理论之感知器与最大间隔分类器
查看>>
Be Nice!要善良
查看>>
二、ansible配置简要介绍
查看>>
解决docker容器中无ifconfig命令和ping命令问题
查看>>
CHAR、TCHAR、WCHAR_T之间的区别与问题
查看>>
sql小计合计
查看>>
安装Java
查看>>
Ubuntu Linux输入法fcitx方块乱码解决设置
查看>>
node递归批量重命名指定文件夹下的文件
查看>>
python if not用法
查看>>
python-2
查看>>
选择器
查看>>