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. 360你吃屎啊你,hao123,12345等等

    请看到这个文章的小伙伴将文章看完,看看我的感受是有多深,谢谢了 现在浏览器已经是人们经常用的东西,相信都有时不时就差度娘的习惯吧 也就是说每个人都有自己喜欢的主页 可电脑有时候就是遭不住,360什么的 ...

  2. kafka 0.10.2 消息生产者

    package cn.xiaojf.kafka.producer; import org.apache.kafka.clients.producer.KafkaProducer; import org ...

  3. Python多线程和多进程谁更快?

    python多进程和多线程谁更快 python3.6 threading和multiprocessing 四核+三星250G-850-SSD 自从用多进程和多线程进行编程,一致没搞懂到底谁更快.网上很 ...

  4. python基础 - 01

    python 变量名 在python中的变量命名,与其他语言大体相似,变量的命名规则如下: 变量名是数字.字母.下划线的任意组合 变量名的第一个字符不能是数字 系统的关键字不能设置为变量名    Ti ...

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

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

  6. int 与 int *

    #include <iostream>using namespace std;int QKPass(int* , int , int);  //若声明为 int QKPass(int, i ...

  7. GPU编程-Thread Hierarchy(3)

    1. 如果处理的数据是二维的或者三维的,应该怎么办呢? 针对的,我们可以按照二维或者三维的方式,组织线程.老规矩,先代码.后解释 // Kernel definition __global__ voi ...

  8. PHP版本替换, phpinfo和php -v显示版本信息不一致

    环境:OS X EI Capitan 10.11 & lnmp 背景: 1想将lamp(xampp安装的,php5.2)换成 lnmp(php7.0)   2php5.2卸载(xampp卸载& ...

  9. Azure经典门户创建VM,如何设置使用静态IP地址?

    使用 Azure 经典管理门户中创建的虚拟机,无法使用静态IP 地址,在管理界面没有该设置.在新的管理门户中虽然有使用静态IP的设置,但是选项是灰色,无法修改,提示错误:This virtual ma ...

  10. iOS开发之常用资讯类App的分类展示与编辑的完整案例实现(Swift版)

    上篇博客我们聊了<资讯类App常用分类控件的封装与实现(CollectionView+Swift3.0)>,今天的这篇博客就在上篇博客的基础上做些东西.做一个完整的资讯类App中的分类展示 ...