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. 忘记block格式 xib加载没有计算导航栏和tabbar的大小

    敲inlineBlock xib加载没有计算导航栏和tabbar的大小 /将这个属性改为no self.tabBarController.tabBar.translucent = NO; 判断优化,两 ...

  2. 关于STM32空闲中断

    有一次做一个东西,为了尽量不占用CPU的处理数据时间,所以就使用DMA接收串口的数据,但是呢问题来了.,,,,,怎么样才能确定接收到了一条完整的数据了,,我们都知道只要打开DMA 那家伙就不停的把接收 ...

  3. 由Find All References引发的思考。,

    今天在研究C#代码问题的时候遇到了一个Visual Studio的小问题.在Visual Studio 2013中,使用Find All References功能不能找到同一类型不同版本的所有引用,具 ...

  4. MVC+Bootstrap+Drapper使用PagedList.Mvc支持多查询条件分页

    前几天做一个小小小项目,使用了MVC+Bootstrap,以前做分页都是异步加载Mvc部分视图的方式,因为这个是小项目,就随便一点.一般的列表页面,少不了有查询条件,下面分享下Drapper+Page ...

  5. 小小白的python之路------python基础01

    1. 不说python是啥了,百度一堆.,还是说说我学了啥 我说的是python3.5,其他的自己看着办 这个是下载链接啊,自己玩 https://www.python.org/ 我下载完成,使用py ...

  6. canvas动画——粒子系统(1)

    这个动画在很早之前就见过,当时就没迷住了.最近在学canavs动画,动手实现了一下.代码在这里.展示效果在这里. 这属于粒子系统的一种,粒子系统就是需要管理一堆粒子嘛,动画实现的关键在于,遍历这些粒子 ...

  7. Hadoop之WordCount详解

    花了好长时间查找资料理解.学习.总结 这应该是一篇比较全面的MapReduce之WordCount文章了 耐心看下去 1,创建本地文件 在hadoop-2.6.0文件夹下创建一个文件夹data,在其中 ...

  8. 第41篇 推荐一个jekyll博客模板

    本人用的模板是基于Codeboy的博客模板改造模板,(由于本人可能会有很多样式修改,所以不再将修改pullrequst到原项目,在此对codeboy模板表示感谢).功能改造如下: 添加微信支付宝打赏 ...

  9. cpp(第二章)

    1. 函数参数空着,代表void 2. 换行符 endl(确保程序继续运行前刷新输出,将其立即显示在屏幕上)|| '\n' (不能保证,这意味着有些系统中,有时可能输入信息后才会出现) 3.小谈cou ...

  10. Elasticsearch索引和文档操作

    列出所有索引 现在来看看我们的索引 GET /_cat/indices?v 响应 health status index uuid pri rep docs.count docs.deleted st ...