LinkedList由双向链表实现的集合,因此可以从头或尾部双向循环遍历。

LinkedList的操作都是对双向链表的操作,理解双向链表的数据结构就很容易理解LinkedList的实现。

双向链表由带前驱和后继的节点构成,简易如下:

如果添加一个c节点,简易步骤如下:

先创建一个新节点。然后把原先的last节点的next指向新节点,在把新节点的pre指向原先的last,最后新节点指为last节点。

具体的双向链表还是参考数据结构的资料。

一、构造方法

1、无参的

    public LinkedList() {
}

2、集合为参数的

    public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
// 检查索引
checkPositionIndex(index); Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false; Node<E> pred, succ;
// 索引为尾部还是范围内的
if (index == size) {
succ = null;
pred = last;
} else {
succ = node(index);
pred = succ.prev;
} for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
first = newNode;
else
pred.next = newNode;
pred = newNode;
} if (succ == null) {
last = pred;
} else {
pred.next = succ;
succ.prev = pred;
} size += numNew;
modCount++;
return true;
}
private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size;
}

二、添加元素

1、add(E e)方法,添加节点到尾部

    public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
// 尾节点赋值给l
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++;
}

2、addFirst(E e)方法,添加节点到首部

    public void addFirst(E e) {
linkFirst(e);
}
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}

三、删除元素

1、remove(Object o)方法,删除o节点(只删除一次),循环链表找到要删除的节点,然后调用unlink()方法进行删除。

    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; if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
} if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
} x.item = null;
size--;
modCount++;
return element;
}

2、removeFirst()方法,删除首节点,为空则抛异常。

    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 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 void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
} /**
* 从尾部添加元素
*/
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++;
} /**
* 在指定元素前插入元素
*/
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++;
} /**
* 删除首节点(私有的,内部使用)
*/
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;
} /**
* 删除尾节点(私有的,内部使用)
*/
private E unlinkLast(Node<E> l) {
// assert l == last && l != null;
final E element = l.item;
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // help GC
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
} /**
* 删除节点x
*/
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;
} if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
} x.item = null;
size--;
modCount++;
return element;
} /**
* 获取首节点
*/
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
} /**
* 获取尾节点
*/
public E getLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return l.item;
} /**
* 删除首节点并返回元素值
*/
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
} /**
* 删除尾节点并返回元素值
*/
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
} /**
* 把e设为首节点
*/
public void addFirst(E e) {
linkFirst(e);
} /**
* 把e设为尾节点
*/
public void addLast(E e) {
linkLast(e);
} /**
* 判断o是否在集合中
*/
public boolean contains(Object o) {
return indexOf(o) != -1;
} /**
* 集合大小
*/
public int size() {
return size;
} /**
* 添加元素到链表尾部
*/
public boolean add(E e) {
linkLast(e);
return true;
} /**
* 删除o节点
*/
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;
} /**
* 添加集合
*/
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
} /**
* 指定位置添加集合
*/
public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index); Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false; Node<E> pred, succ;
if (index == size) {
succ = null;
pred = last;
} else {
succ = node(index);
pred = succ.prev;
} for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
first = newNode;
else
pred.next = newNode;
pred = newNode;
} if (succ == null) {
last = pred;
} else {
pred.next = succ;
succ.prev = pred;
} size += numNew;
modCount++;
return true;
} /**
* 清除集合所有元素
*/
public void clear() {
// Clearing all of the links between nodes is "unnecessary", but:
// - helps a generational GC if the discarded nodes inhabit
// more than one generation
// - is sure to free memory even if there is a reachable Iterator
for (Node<E> x = first; x != null; ) {
Node<E> next = x.next;
x.item = null;
x.next = null;
x.prev = null;
x = next;
}
first = last = null;
size = 0;
modCount++;
} // Positional Access Operations /**
* 获取指定位置的元素的值
*/
public E get(int index) {
checkElementIndex(index);
return node(index).item;
} /**
* 取代指定位置的元素并返回原元素的值
*/
public E set(int index, E element) {
checkElementIndex(index);
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
} /**
* 添加元素到指定位置并后移原先的元素,如果指定的位置是最后,则直接添加元素在尾部
*/
public void add(int index, E element) {
checkPositionIndex(index); if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
} /**
* 删除指定位置的元素
*/
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
} /**
* 用于判断元素索引是否正确
*/
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
} /**
* 用于判断位置索引是否正确
*/
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size;
} /**
* 越界异常提示
*/
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
} private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
} private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
} /**
* 返回指定位置的节点.
*/
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;
}
} // Search Operations /**
* 从头循环返回第一次出现o的index
*/
public int indexOf(Object o) {
int index = 0;
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
} /**
* 从尾循环返回第一次出现o的index
*/
public int lastIndexOf(Object o) {
int index = size;
if (o == null) {
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (x.item == null)
return index;
}
} else {
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (o.equals(x.item))
return index;
}
}
return -1;
} // Queue operations. /**
* 返回首节点的值,但不删除,null也可以返回
*/
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
} /**
* 返回首节点的值,但不删除,如果是null则抛NoSuchElementException异常
*/
public E element() {
return getFirst();
} /**
* 返回首节点并删除
*/
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
} /**
* 返回首节点并删除,如果首节点为null抛异常
*/
public E remove() {
return removeFirst();
} /**
* 添加元素到尾节点
*/
public boolean offer(E e) {
return add(e);
} // Deque operations
/**
* 添加元素到首节点前面
*/
public boolean offerFirst(E e) {
addFirst(e);
return true;
} /**
* 添加元素到尾节点后面
*/
public boolean offerLast(E e) {
addLast(e);
return true;
} /**
* 获取首节点不删除
*/
public E peekFirst() {
final Node<E> f = first;
return (f == null) ? null : f.item;
} /**
* 获取尾节点不删除
*/
public E peekLast() {
final Node<E> l = last;
return (l == null) ? null : l.item;
} /**
* 获取首节点并删除
*/
public E pollFirst() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
} /**
* 获取尾节点并删除
*/
public E pollLast() {
final Node<E> l = last;
return (l == null) ? null : unlinkLast(l);
} /**
* 添加元素到首节点前面
*/
public void push(E e) {
addFirst(e);
} /**
* 移除并返回首节点
*/
public E pop() {
return removeFirst();
} // 节点构造
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;
}
} /**
* 集合转成数组
*/
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
return result;
}
}

LinkedList源码浅析(jdk1.8)的更多相关文章

  1. 死磕Java之聊聊LinkedList源码(基于JDK1.8)

    工作快一年了,近期打算研究一下JDK的源码,也就因此有了死磕java系列 LinkedList 是一个继承于AbstractSequentialList的双向链表,链表不需要capacity的设定,它 ...

  2. java集合: LinkedList源码浅析

    LinkedList 数据结构是双向链表,插入删除比较方便.LinkedList 是线程不安全的,允许元素为null  . 构造函数: 构造函数是空的. /** * Constructs an emp ...

  3. HashMap源码浅析(jdk1.8)

    HashMap是以key-value键值对的形式进行存储数据的,数据结构是以数组+链表或红黑树实现. 数据结构图如下: 一.关键属性 HashMap初始化和方法使用的属性. /** * 默认初始容量1 ...

  4. ArrayList源码分析--jdk1.8

    ArrayList概述   1. ArrayList是可以动态扩容和动态删除冗余容量的索引序列,基于数组实现的集合.  2. ArrayList支持随机访问.克隆.序列化,元素有序且可以重复.  3. ...

  5. ReentrantLock源码分析--jdk1.8

    JDK1.8 ArrayList源码分析--jdk1.8LinkedList源码分析--jdk1.8HashMap源码分析--jdk1.8AQS源码分析--jdk1.8ReentrantLock源码分 ...

  6. 给jdk写注释系列之jdk1.6容器(2)-LinkedList源码解析

    LinkedList是基于链表结构的一种List,在分析LinkedList源码前有必要对链表结构进行说明.   1.链表的概念      链表是由一系列非连续的节点组成的存储结构,简单分下类的话,链 ...

  7. java并发:jdk1.8中ConcurrentHashMap源码浅析

    ConcurrentHashMap是线程安全的.可以在多线程中对ConcurrentHashMap进行操作. 在jdk1.7中,使用的是锁分段技术Segment.数据结构是数组+链表. 对比jdk1. ...

  8. Java集合基于JDK1.8的LinkedList源码分析

    上篇我们分析了ArrayList的底层实现,知道了ArrayList底层是基于数组实现的,因此具有查找修改快而插入删除慢的特点.本篇介绍的LinkedList是List接口的另一种实现,它的底层是基于 ...

  9. LinkedList源码解析

    LinkedList是基于链表结构的一种List,在分析LinkedList源码前有必要对链表结构进行说明.1.链表的概念链表是由一系列非连续的节点组成的存储结构,简单分下类的话,链表又分为单向链表和 ...

随机推荐

  1. A function to help graphical model checks of lm and ANOVA(转)

    As always a more colourful version of this post is available on rpubs. Even if LM are very simple mo ...

  2. JavaScript中return的用法详解

    JavaScript中return的用法详解 最近,跟身边学前端的朋友了解,有很多人对函数中的this的用法和指向问题比较模糊,这里写一篇博客跟大家一起探讨一下this的用法和指向性问题. 1定义 t ...

  3. 移动前端meta

    <!-- 页面描述 --> <meta name="description" content="不超过150个字符"/> <!-- ...

  4. 将 FFmpeg 移植到 Android平台 (完整版)

    首先需要去FFmpeg的官网http://www.ffmpeg.org/去下载FFmpeg的源码,目前的版本号为FFmpeg3.3(Hilbert). 下载的文件为压缩包,解压后得到ffmpeg-3. ...

  5. VMware Workstation 11安装

    VMware Workstation 11序列号:1F04Z-6D111-7Z029-AV0Q4-3AEH8

  6. 2015阿里巴巴安全峰会PPT

    有幸参加了阿里巴巴安全峰会,不得不佩服阿里巴巴神盾局,真牛B!然后亲眼目睹了第二天的各大厂商牛(zhuang)B人才上台演讲,有被捧的,有被喷的,呵呵.总的来说,大家的分享精神还是阔以的. 下面是会议 ...

  7. js继承的常用方法

    写在前面的话:这篇博客不适合对面向对象一无所知的人,如果你连_proto_.prototype...都不是很了解的话,建议还是先去了解一下JavaScript面向对象的基础知识,毕竟胖子不是一口吃成的 ...

  8. js获取页面宽高

    网页可见区域宽:document.body.clientWidth网页可见区域高:document.body.clientHeight网页可见区域宽:document.body.offsetWidth ...

  9. scrapy配置

    scrapy配置 增加并发 并发是指同时处理的request的数量.其有全局限制和局部(每个网站)的限制. Scrapy默认的全局并发限制对同时爬取大量网站的情况并不适用,因此您需要增加这个值. 增加 ...

  10. Mac 性能测试环境搭建——理论篇

    此篇为博主原创内容,若转载请写明出处,谢谢! 前言在搭建之初,我们要思考的2个点:1.性能怎么测试?2.性能的测试环境如何搭建(该如何去做)?1.什么是性能?    个人理解为:合理的架构.低耦合.高 ...