源自: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. Jenkins+maven+git配置

    1)         安装maven 如下图我已装好maven(这是我很早以前装的,安装教程大家可以百度一下,很容易安装的) 2)         安装git客户端 如下图所示,我也安装好了git客户 ...

  2. Python内置函数(65)——staticmethod

    英文文档: staticmethod(function) Return a static method for function. A static method does not receive a ...

  3. First:安装配置JDK and 部署Tomcat

    (一)准备 百度云地址(win,64Bit): 1.tomcat(7.0):链接:https://pan.baidu.com/s/1f60DOGO5Hnj9bq-987FNrw 密码:6q55 2.j ...

  4. 浅谈Web网站的架构演变过程

    前言 我们以javaweb为例,来搭建一个简单的电商系统,看看这个系统可以如何一步步演变.   该系统具备的功能:   用户模块:用户注册和管理 商品模块:商品展示和管理 交易模块:创建交易和管理 阶 ...

  5. python/socket编程之粘包

    python/socket编程之粘包 粘包 只有TCP有粘包现象,UDP永远不会粘包. 首先需要掌握一个socket收发消息的原理 发送端可以是1k,1k的发送数据而接受端的应用程序可以2k,2k的提 ...

  6. DIY一个超简单的画图程序

    编译环境:VS2017+Easy_X 最近笔者一直在翻阅Easy_X的帮助手册,学习到了一些关于获取鼠标状态消息函数的知识,感觉收获颇大,于是想试验一番,将所学知识运用出来.先补充一下在Easy_X中 ...

  7. 1.3WEB API 默认以json格式返回数据,同时定义时间格式,返回格式

    首先我们知道,web api 是可以返回任意类型的,然后在输出的过程中转为(默认的)xml. 但是xml是比较费流量的,而且大多前端都是用json对接,所以我们也只能随大流,把它输出改成json. 不 ...

  8. linux下的mysql安装

    写在开头的小故事: 很久以前小石头我在一家公司做运维工程师,当时我们有一台认证服务器安装了mysql5.5版本.有一天领导说防止它挂掉,做个主从复制吧,我开心的接受任务,但是让某同事听到了, 此同事代 ...

  9. [js]关于call()和apply()的理解

    call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向. 因为 JavaScript 的函数存在「定义时上下文」和 ...

  10. 关于if后面直接加上参数名,不加条件的用法

    <template> <section> <p v-if="aa">{{aa}}</p> <p v-if="bb&q ...