基本介绍

Linkedlist基于链表的动态数组(双向链表):

    可以被当作堆栈(后进先出)、队列(先进先出)或双端队列进行操作。

    数据添加删除效率高,只需要改变指针指向即可,但是访问数据的平均效率低,需要对链表进行遍历。

    非同步,线程不安全。

    支持null元素、有顺序、元素可以重复

    不要使用普通for循环去遍历LinkedList,使用迭代器或者foreach循环(foreach循环的原理就是迭代器)去遍历LinkedList即可:
这种方式是直接按照地址去找数据的,将会大大提升遍历LinkedList的效率。

源码分析

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable {

    //实际大小
transient int size = 0; //头节点
transient Node<E> first; //尾节点
transient Node<E> last; public LinkedList() {
} public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
} //双向链表
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev; Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
} //添加在头节点
private void linkFirst(E e) {
//旧头节点
final Node<E> f = first;
//新节点的next指向旧头节点
final Node<E> newNode = new Node<>(null, e, f);
//头节点改成新节点
first = newNode;
//如果旧头节点为null,表示空链表,尾节点也指向新节点
if (f == null)
last = newNode;
//旧头节点的prev指向新节点
else
f.prev = newNode;
size++;
modCount++;
} //添加到链表尾部
public boolean add(E e) {
linkLast(e);
return true;
} void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
} public void add(int index, E element) {
//检查index是否合理
checkPositionIndex(index);
//如果index是size,则添加在尾部
if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
} //查找index处的节点
Node<E> node(int index) {
// assert isElementIndex(index); //如果index在左半边,则从头遍历(提到查找效率)
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
//如果index在右半边,则从尾遍历(提到查找效率)
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
} void linkBefore(E e, Node<E> succ) {
// assert succ != null;
//旧节点的前一个节点
final Node<E> pred = succ.prev;
//将新节点设置为:prev为旧节点的前一个节点,next为旧节点
final Node<E> newNode = new Node<>(pred, e, succ);
//旧节点的prev指向新节点
succ.prev = newNode;
//旧节点的前一个节点是空,表示旧节点是头节点,则重设头节点
if (pred == null)
first = newNode;
//旧节点的前一个节点的next指向新节点
else
pred.next = newNode;
size++;
modCount++;
} public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
} private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> 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 E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
} E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
//要删除元素的后一个
final Node<E> next = x.next;
//要删除元素的前一个
final Node<E> prev = x.prev;
//如果前是空,表示删除头元素,后变成头元素
if (prev == null) {
first = next;
} else {
//前的下一个变成后
prev.next = next;
x.prev = null; //帮助GC
}
//如果后是空,表示删除尾元素,前变成尾元素
if (next == null) {
last = prev;
} else {
//后的上一个变成前
next.prev = prev;
x.next = null; //帮助GC
} x.item = null; //帮助GC
size--;
modCount++;
return element;
} public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
} public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
}

Linkedlist 详解的更多相关文章

  1. 【Java集合】LinkedList详解前篇

    [Java集合]LinkedList详解前篇 一.背景 最近在看一本<Redis深度历险>的书籍,书中第二节讲了Redis的5种数据结构,其中看到redis的list结构时,作者提到red ...

  2. LinkedList详解-源码分析

    LinkedList详解-源码分析 LinkedList是List接口的第二个具体的实现类,第一个是ArrayList,前面一篇文章已经总结过了,下面我们来结合源码,学习LinkedList. 基于双 ...

  3. java集合类之LinkedList详解

    一.LinkedList简介 由于LinkedList是一个实现了Deque的双端队列,所以LinkedList既可以当做Queue,又可以当做Stack,在将LinkedList当做Stack时,使 ...

  4. Java的LinkedList详解,看源码之后的总结

    1. LinkedList实现了一个带表头的双向循环链表: 2. LinkedList是线程不同步的: 3. LinkedList中实现了push.pop.peek.empty等方法,因此Linked ...

  5. java集合框架-List集合ArrayList和LinkedList详解

    List 集合源码剖析 ✅ ArrayList 底层是基于数组,(数组在内存中分配连续的内存空间)是对数组的升级,长度是动态的. 数组默认长度是10,当添加数据超越当前数组长度时,就会进行扩容,扩容长 ...

  6. Java容器解析系列(5) AbstractSequentialList LinkedList 详解

    AbstractSequentialList为顺序访问的list提供了一个骨架实现,使实现顺序访问的list变得简单; 我们来看源码: /** AbstractSequentialList 继承自 A ...

  7. 【Java入门提高篇】Day27 Java容器类详解(九)LinkedList详解

    这次介绍一下List接口的另一个践行者——LinkedList,这是一位集诸多技能于一身的List接口践行者,可谓十八般武艺,样样精通,栈.队列.双端队列.链表.双向链表都可以用它来模拟,话不多说,赶 ...

  8. LinkedList详解

    一.LinkedList的介绍与特点. 1.继承实现关系. 实现了双端队列接口Deque,因此具有双端队列的功能:addFirt,addLast,offerFirt,offerLast,removeF ...

  9. [Swift实际操作]八、实用进阶-(9)Swift中的链表LinkedList详解

    链表是一种物理存储单元上的非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的.相比于线性表的顺序结构,链表比较方便插入和删除操作.本文将讲解如何模拟一个链表. //链表的节点 ...

  10. 【Java集合】LinkedList详解中篇

    这是关于LinkedList的第二篇文章,我将会源码分析LinkedList的部分重要代码,关键地方我都有注释说明,希望大家能比较明白的看懂! 分析源码按照顺序分析: 变量 构造方法 方法 一.变量 ...

随机推荐

  1. 从零开始搭建系统2.8——HDFS安装及配置

    从零开始搭建系统2.8——HDFS安装及配置

  2. 【Luogu】【关卡2-16】线性动态规划(2017年10月)【还差三道题】

    任务说明:这也是基础的动态规划.是在线性结构上面的动态规划,一定要掌握. P1020 导弹拦截 导弹拦截 P1091 合唱队形 老师给同学们排合唱队形.N位同学站成一排,音乐老师要请其中的(N-K)位 ...

  3. python_django_上传文件

    存储路径: 存储在服务器的项目的static/upfile(你说了算的文件名,但是一般俺们叫这个)文件中 配置: 配置settings.py文件 MDEIA_ROOT = os.path.join(B ...

  4. 再也不用字符串拼接dom元素了

    <script type="text/html" id="tmp"> <div class="cla"> <u ...

  5. Vue学习笔记【8】——在Vue中使用样式

    使用class样式 数组 <h1 :class="['red', 'thin']">这是一个邪恶的H1</h1> 2.数组中使用三元表达式 <h1 : ...

  6. Java——面向对象知识总结

    面向对象的三条主线: 一.类及类的成分 1.类与类的关系: java程序是关注于类的设计. 类从代码的角度:并列关系! 从执行.设计的角度:关联关系.继承关系.聚合关系 class A{ } clas ...

  7. Python 修改在使用ddt时测试报告默认显示用例名称与预期不符

    正常在不使用ddt时,在方法下添加注释,即可作为用例描述("""用例描述""") @BeautifulReport.add_test_img ...

  8. PHP FILTER_SANITIZE_NUMBER_INT 过滤器

    定义和用法 FILTER_SANITIZE_NUMBER_INT 过滤器删除数字中所有非法的字符. 该过滤器允许所有数字以及 . + - Name: "number_int" ID ...

  9. PHP ftp_mdtm() 函数

    ftp_mdtm() 函数返回指定文件的最后修改时间. 该函数将以 Unix 时间戳的形式返回文件的最后修改时间,如果出错则返回 -1. 语法 int ftp_mdtm ( resource $ftp ...

  10. 【LeetCode 9】回文数

    题目链接 [题解] 还是要注意,取反的时候,-2^31 取反的话会爆掉Int..(因为int的正数最多到2^31-1) [代码] class Solution { public: bool isPal ...