基本介绍

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. kubernetes报错

    错误信息:执行yaml文件后,服务在运行,但是提示命令找不到 原因:没有环境,相当于只有一个快捷方式 环境目录为/usr/local/bin 解决办法:将/etc/ansible/bin下的文件都拷贝 ...

  2. asp.net网站Application_Start疑是不执行的现象

    今天遇见了一个很诡异的事情,发布了新代码后,发现在Application_Start中读取的一些配置参数变为空了,最开始我以为是什么特殊的原因程序没有执行Application_Start,导致它们的 ...

  3. mongodb的学习 (1)

    1. 启动服务 (1)在D盘下新建mongodb 文件夹,在mongodb 文件夹里面新建db; (2)win+R 启动cmd ,输入 `mongod --dbpath "D:/mongod ...

  4. spring中后台接收参数总结

    @RequestParam注解用于将指定的请求参数赋值给方法的参数 @RequestMapping(“/login”) public void login(@RequestParam(name=“lo ...

  5. Sublime Text添加gcc编译器

    { "shell_cmd" : "gcc $file_name -o ${file_base_name}", "working_dir" : ...

  6. springboot集成使用rabbitmq笔记(2.rabbitmq使用)

    使用rabbitmq笔记一 使用rabbitmq笔记二 使用rabbitmq笔记三 1.引入包 <dependencies> <dependency> <groupId& ...

  7. 阿里云物联网边缘计算加载MQTT驱动

    写在前面 本文在LinkEdge快速入门样例驱动的基础上,加载了MQTT订阅的客户端,使得边缘端容器可以通过MQTT获得外部数据. 1. 系统需求 物联网边缘计算平台,又名Link IoT Edge[ ...

  8. 【LeetCode 27】移除元素

    题目链接 [题解] 沙比提 [代码] class Solution { public: int removeElement(vector<int>& nums, int val) ...

  9. Android中的Toast重复显示的问题

    Toast是Android中用来显示信息的一种机制,和Dialog不一样的是,Toast是没有焦点,而且Toast显示的时间有限,过一定的时间就会自动消失. Toast一般用来提示用户的误操作.但是如 ...

  10. homebrew -- mac os 系统下的 apt-get、yum

    linux下有很方便的包管理器如:apt-get.yum,mac下也有类似的工具:Homebrew 和 Fink.MacPort.Flink是直接编译好的二进制包,MacPorts是下载所有依赖库的源 ...