源自:jdk1.8.0_121

LinkedList继承自AbstractSequentialList,实现了ListDequeCloneableSerializable

LinkedList内部是一个双向链表

变量

    transient int size = 0;

    // 链表的第一个结点
transient Node<E> first; // 链表的最后一个结点
transient Node<E> last;

构造方法

    public LinkedList() {
} public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}

LinkedList$Node

NodeLinkedList的内部类,所有增加、修改结点的操作都是通过Node对象

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

add方法

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

remove方法

remove有两个重载方法,分别是remove(int index)remove(Object o)

    // 删除索引对应的结点
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
// 删除一个值(重复的也只会删除其中一个)
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
} 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; // 将x与x.prev从链表中断开
if (prev == null) {
first = next;
} else {
// 将x.prev.next = x 变为 x.prev.next = x.next
prev.next = next;
x.prev = null;
} // 将x与x.next从链表中断开
if (next == null) {
last = prev;
} else {
// 将x.next.prev = x 变为 x.next.prev = x.prev
next.prev = prev;
x.next = null;
} x.item = null;
// 实际数量-1
size--;
// 操作次数+1
modCount++;
// 返回删除的结点值
return element;
} Node<E> node(int index) {
// assert isElementIndex(index);
// 如果索引小于实际大小的一半,就从索引的左边遍历,反之。
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}

由于LinkedList的node方法是通过索引逐一遍历,因此查找的效率会比ArrayList直接在数组中找到索引对应的值慢的多。

java集合之LinkedList源码解读的更多相关文章

  1. Java集合(五)--LinkedList源码解读

    首先看一下LinkedList基本源码,基于jdk1.8 public class LinkedList<E> extends AbstractSequentialList<E> ...

  2. 死磕 java集合之LinkedList源码分析

    问题 (1)LinkedList只是一个List吗? (2)LinkedList还有其它什么特性吗? (3)LinkedList为啥经常拿出来跟ArrayList比较? (4)我为什么把LinkedL ...

  3. 【Java集合】ArrayDeque源码解读

    简介 双端队列是一种特殊的队列,它的两端都可以进出元素,故而得名双端队列. ArrayDeque是一种以循环数组方式实现的双端队列,它是非线程安全的. 它既可以作为队列也可以作为栈. 继承体系 Arr ...

  4. Java集合:LinkedList源码解析

    Java集合---LinkedList源码解析   一.源码解析1. LinkedList类定义2.LinkedList数据结构原理3.私有属性4.构造方法5.元素添加add()及原理6.删除数据re ...

  5. Java集合之LinkedList源码分析

    概述 LinkedLIst和ArrayLIst一样, 都实现了List接口, 但其内部的数据结构不同, LinkedList是基于链表实现的(从名字也能看出来), 随机访问效率要比ArrayList差 ...

  6. Java集合之LinkedList源码解析

    LinkedList简介 LinkedList基于双向链表,即FIFO(先进先出)和FILO(先进后出)都是支持的,这样它可以作为堆栈,队列使用 继承AbstractSequentialList,该类 ...

  7. Java 集合之LinkedList源码分析

    1.介绍 链表是数据结构中一种很重要的数据结构,一个链表含有一个或者多个节点,每个节点处理保存自己的信息之外还需要保存上一个节点以及下一个节点的指针信息.通过链表的表头就可以访问整个链表的信息.Jav ...

  8. java集合之ArrayList源码解读

    源自:jdk1.8.0_121 ArrayList继承自AbstractList,实现了List.RandomAccess.Cloneable.Serializable. ArrayList内部是通过 ...

  9. Java集合干货——LinkedList源码分析

    前言 在上篇文章中我们对ArrayList对了详细的分析,今天我们来说一说LinkedList.他们之间有什么区别呢?最大的区别就是底层数据结构的实现不一样,ArrayList是数组实现的(具体看上一 ...

随机推荐

  1. selenium的Python使用(一)浏览器驱动的安装及使用

    一.selenium的安装 直接使用pip进行安装 pip install selenium    #(安装最新版本) pip install selenium==3.6.0   #(安装指定版本) ...

  2. C语言头文件引用

    1,引用分为两种 firs:include<fileName.h> 引用系统头文件一般用<>. second:include"fileName.h" 引用自 ...

  3. Sphinx主索引和增量索引来实现索引实时更新的关键步骤

    1.配置csft.conf文件 vim /etc/csft.conf # # Minimal Sphinx configuration sample (clean, simple, functiona ...

  4. 阿里云API网关(11)API的三种安全认证方式

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  5. Spring Security入门(3-8)Spring Security获取session中的UserDetail

  6. My97设置开始、结束 时间区间及输入框不能输入只能选择的方法

    时间区间开始: <input type="text" id = "first_time" name="first_time" valu ...

  7. 初识JavaScript闭包

    一个问题引发的思考 在我学习javascript的事件时,有一个小任务是使用JS来实现 li 列表项在鼠标悬浮时会有背景阴影的动态效果,很自然想到用for 来为每个列表项添加onmouseover 和 ...

  8. Hibernate(九):基于主键映射的1-1关联关系

    背景: 在实际开发中我们会遇到新建一个用户表,但这个表字段过长,而且有写字段常用(主要),有些字段比较不常用(次要).此时,我们会考虑到把用户信息拆分到两张表中:member(存储用户主要信息),me ...

  9. 使用 vue-i18n 切换中英文

    兼容性: 支持 Vue.js 2.x 以上版本 安装方法:(此处只演示 npm) npm install vue-i18n 使用方法: 1.在 main.js 中引入 vue-i18n (前提是要先引 ...

  10. js中call和apply的用法

    1. 每个函数都包含两个非继承而来的方法:call()方法和apply()方法. 2. 相同点:这两个方法的作用是一样的. 都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖 ...