LinkedList的实现原理
转载:http://wiki.jikexueyuan.com/project/java-collection/linkedlist.html
概述
LinkedList 和 ArrayList 一样,都实现了 List 接口,但其内部的数据结构有本质的不同。LinkedList 是基于链表实现的(通过名字也能区分开来),所以它的插入和删除操作比 ArrayList 更加高效。但也是由于其为基于链表的,所以随机访问的效率要比 ArrayList 差。
看一下 LinkedList 的类的定义:
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{}
LinkedList 继承自 AbstractSequenceList,实现了 List、Deque、Cloneable、java.io.Serializable 接口。AbstractSequenceList 提供了List接口骨干性的实现以减少实现 List 接口的复杂度,Deque 接口定义了双端队列的操作。
在 LinkedList 中除了本身自己的方法外,还提供了一些可以使其作为栈、队列或者双端队列的方法。这些方法可能彼此之间只是名字不同,以使得这些名字在特定的环境中显得更加合适。
LinkedList 也是 fail-fast 的(前边提过很多次了)。
LinkedList 源码解读
数据结构
LinkedList 是基于链表结构实现,所以在类中包含了 first 和 last 两个指针(Node)。Node 中包含了上一个节点和下一个节点的引用,这样就构成了双向的链表。每个 Node 只能知道自己的前一个节点和后一个节点,但对于链表来说,这已经足够了。
transient int size = 0;
transient Node<E> first; //链表的头指针
transient Node<E> last; //尾指针
//存储对象的结构 Node, LinkedList的内部类
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(E e)
该方法是在链表的 end 添加元素,其调用了自己的方法 linkLast(E e)。
该方法首先将 last 的 Node 引用指向了一个新的 Node(l),然后根据l新建了一个 newNode,其中的元素就为要添加的 e;而后,我们让 last 指向了 newNode。接下来是自身进行维护该链表。
/**
* Appends the specified element to the end of this list.
*
* <p>This method is equivalent to {@link #addLast}.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
linkLast(e);
return true;
}
/**
* Links e as last element.
*/
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++;
}
add(int index, E element)
该方法是在指定 index 位置插入元素。如果 index 位置正好等于 size,则调用 linkLast(element) 将其插入末尾;否则调用 linkBefore(element, node(index))方法进行插入。该方法的实现在下面,大家可以自己仔细的分析一下。(分析链表的时候最好能够边画图边分析)
/**
* Inserts the specified element at the specified position in this list.
* Shifts the element currently at that position (if any) and any
* subsequent elements to the right (adds one to their indices).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
checkPositionIndex(index);
if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}
/**
* Inserts element e before non-null Node succ.
*/
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
LinkedList 的方法实在是太多,在这没法一一举例分析。但很多方法其实都只是在调用别的方法而已,所以建议大家将其几个最核心的添加的方法搞懂就可以了,比如 linkBefore、linkLast。其本质也就是链表之间的删除添加等。
LinkedList的实现原理的更多相关文章
- Java LinkedList的实现原理
LinkedList是Java List类型的集合类的一种实现,此外,LinkedList还实现了Deque接口.本文基于Java1.8,对于LinkedList的实现原理做一下详细讲解. (Java ...
- Java-链表LinkedList源码原理分析,并且通过LinkedList构建队列
在这里我们介绍一下最简单的链表LinkedList: 看一下add()方法: public boolean add(E e) { linkLast(e); return true; } void li ...
- Java集合之ArrayList和LinkedList的实现原理以及Iterator详解
ArrayList实现可变数组的原理: 当元素超出数组内容,会产生一个新数组,将原来数组的数据复制到新数组中,再将新的元素添加到新数组中. ArrayList:是按照原数组的50%来延长,构造一个初始 ...
- LinkedList 底层实现原理
LinkedList的底层实现原理 LinkedList 底层数据结构为双向链表,链表结构,基于一个个链表节点Node 1,Inner Class 内部类 private static class N ...
- JDK1.8中LinkedList的实现原理及源码分析
详见:https://blog.csdn.net/cb_lcl/article/details/81222394 一.概述 LinkedList底层是基于双向链表(双向链表的特点, ...
- 集合总结二(LinkedList的实现原理)
一.概述 先来看看源码中的这一段注释,我们先尝试从中提取一些信息: Doubly-linked list implementation of the List and Deque interfaces ...
- LinkedList 的实现原理
本文为博客园作者所写: 一寸HUI,个人博客地址:https://www.cnblogs.com/zsql/ 简单的一个类就直接说了.LinkedList 的底层结构是一个带头/尾指针的双向链表,可以 ...
- LinkedList实现原理(JDK1.8)
LinkedList实现原理(JDK1.8) LinkedList底层采用双向链表,如果对链表这种结构比较熟悉的话,那LinkedList的实现原理看明白就相当容易. 链表通过"指针&quo ...
- 计算机程序的思维逻辑 (39) - 剖析LinkedList
上节我们介绍了ArrayList,ArrayList随机访问效率很高,但插入和删除性能比较低,我们提到了同样实现了List接口的LinkedList,它的特点与ArrayList几乎正好相反,本节我们 ...
随机推荐
- CheckBox的用法
if (window.pageConfig["IsCommend"] == "True") { $("#IsCommend").v ...
- Lintcode: Segment Tree Query II
For an array, we can build a SegmentTree for it, each node stores an extra attribute count to denote ...
- Lintcode: Previous Permuation
Given a list of integers, which denote a permutation. Find the previous permutation in ascending ord ...
- [原创]java WEB学习笔记90:Hibernate学习之路-- -HQL检索方式,分页查询,命名查询语句,投影查询,报表查询
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- UML:时序图
时序图是用来描述对象的状态(或某数值)随时间变化而变化的图,一般软件开发中很少会用到. 灯有开和关两种状态,随着时间的推移,期间有人去开或者关这个灯,用时序图表示如下: 注意:蓝色和红色圈圈.黄色底色 ...
- java中从Spring、Hibernate和Struts框架的action、service和dao三层结构异常处理体系设计
Spring的事务实现采用基于AOP的拦截器来实现,如果没有在事务配置的时候注明回滚的checked exception,那么只有在发生了unchecked exception的时候,才会进行事务回滚 ...
- 夺命雷公狗---DEDECMS----11dedecms字段标签
如果我们在开发的时候需要对获取的某个字段进行二次开发,我们可以对字段值调用某个函数来完成需求, 实例代码如下所示: <!DOCTYPE html> <html> <hea ...
- SQL优化SQL tuning
1. 索引不合适,走主键进行了key lookup查找 说明索引没有覆盖到where条件 或者 orderby 或者 group by的列
- 链接库lib和dl的概念,加载方式的区别
使用LR进行基于windows socket协议做接口测试,只提供了lr_load_dll方法来动态加载动态链接库.之前学习阶段,对TinyXML的学习,使用的静态链接库,当时在程序调用的时候方法也跟 ...
- Eclipse安装插件支持jQuery智能提示
Eclipse安装插件支持jQuery智能提示 最近工作中用到jQuery插件,需要安装eclipse插件才能支持jQuery智能提示,在网上搜索了一下,常用的有三个插件支持jQuery的智能提示:1 ...