基本介绍

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. Centos7命令行安装Tomcat以及配置防火墙开放端口

    [转载]Centos 7 yum安装tomcat 命令: 系统环境CentOS Linux release 7.2.1511 (Core) 一.搭建准备:1.先到tomcat官网https://tom ...

  2. vue-bus全局事件中心简单Demo

    1.vue-cli搭建好项目之后,使用npm安装vue-bus npm install vue-bus 2.在入口文件main.js中全局注册 import Vue from 'vue'; impor ...

  3. loadrunner自定义函数

    https://zhangfy068.iteye.com/blog/1614794 Loadruner 有四种实现自定义函数的方式,根据脚本编写方便性进行选择不同的方式. (1)直接引用法: Acti ...

  4. 线段树求后继+环——cf1237D

    /* 首先开三倍消环(两倍是不够的),倒序求值,线段树找一下后继即可 */ #include<bits/stdc++.h> using namespace std; #define N 3 ...

  5. linux基础知识汇总(四)--ps grep命令

    转:http://www.cnblogs.com/allen8807/archive/2010/11/10/1873843.html http://www.cnblogs.com/end/archiv ...

  6. 浅谈C/C++中的static和extern关键字

    static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.extern "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话 ...

  7. ORM-Dapper:Dapper列表

    ylbtech-ORM-Dapper:Dapper列表 1.返回顶部 1.1. https://dapper-tutorial.net/ 1.2. 2.1. https://www.nuget.org ...

  8. Centos7 安装 telnet 服务

    准备写一个 django-webtelnet(运维管理系统集成后管理网络设备),但是手边没有现成的网络设备资源可以测试,那就研究下 Centos7 下安装 telnet-server 吧. 安装 yu ...

  9. js获取url中的中文参数出现乱码

    解决方法 function getQueryString(key){ var reg = new RegExp("(^|&)"+key+"=([^&]*) ...

  10. 在Windows上安装部署Cuckoo

    1. Cuckoo使用的第三方工具及库 Yara:http://plusvic.github.io/yara/ Pydeep:https://github.com/kbandla/pydeep Yar ...