LinkedList简介
LinkedList是Java语言常用的集合,LinkedList的底层是有一个双向双端链表实现的,因此LinkedList继承了链表的特性:插入删除效率很高(时间复杂度O(1)),查询效率较低(时间复杂度O(N)),不需要给出初始容量,一定程度上节约了系统资源。
下面是LinkedList 的属性定义,以及内部类节点Node的定义。
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
transient int size = 0; //定义了三个变量: size 链表中的元素个数,first 起始节点元素,last 结束节点元素
transient Node<E> first; //链表中的第一个元素
transient Node<E> last; //链表中的最后一个元素
// 内部类,定义一个节点的格式,存在前节点,后节点,以及元素对象
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;
}
}
LinkedList的构造方法
//无参构造,初始化空链表
public LinkedList() {
}
// 有参构造,根据已有集合对象创建链表
public LinkedList(Collection<? extends E> c) {
//创建空链表
this();
//执行添加元素操作
addAll(c);
}
类中用作判断方法
// 判断索引是否有元素
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));
}
addAll() 解释
//向链表追加一个集合的所有对象
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; //集合长度为null,返回false
Node<E> pred, succ; //定义添加位置的临时左节点以及右节点
if (index == size) {
succ = null; //从末尾开始添加,临时右节点为null
pred = last; //临时左节点为尾结点
} else {
succ = node(index); //根据索引返回节点对象
pred = succ.prev; //记录临时左节点
}
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
//创建节点,三个参数:pred 临时左节点,e 元素, null 下个节点
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
first = newNode; //首部添加,首节点为新节点
else
pred.next = newNode; //临时左节点的右节点为新节点
pred = newNode; //新节点为临时左节点
}
if (succ == null) {
last = pred; //临时右节点为null,说明是整天在链表尾部开始添加,尾部节点为临时左节点
} else {
pred.next = succ; //临时左节点的右节点指向临时右节点
succ.prev = pred; //临时右节点的左节点指向临时左节点
}
size += numNew; //链表元素个数添加
modCount++; //变化次数加1
return true; //返回添加成功与否状态
}
类中使用的在首部、尾部、指定位置添加元素以及删除元素方法
// 私有方法:从链表头部添加元素
private void linkFirst(E e) {
final Node<E> f = first;
// 三个参数: null 上一个节点,e 元素.f 下一个节点,f为下一个节点因为是从头部添加.
final Node<E> newNode = new Node<>(null, e, f);
first = newNode; //头部添加,新节点即为头部节点
if (f == null)
last = newNode; //添加第一个节点,尾节点为本身
else
f.prev = newNode; //不是添加第一个节点,将原来链表头部节点左节点指向新头部节点(双向引用)
size++; //链表元素个数加1
modCount++; //修改次数加1
}
// 从链表尾部添加元素
void linkLast(E e) {
final Node<E> l = last;
//三个参数, l 原来尾节点作为新节点的左节点,e 元素,null 自身为新尾节点,所以为null
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode; //链表第一个元素添加,首尾节点均为自身
else
l.next = newNode; //原尾节点右节点指向新节点
size++; //链表元素个数加1
modCount++; //变化次数加1
}
// 在某节点前面添加元素
void linkBefore(E e, Node<E> succ) {
final Node<E> pred = succ.prev; // succ 不能为null,否则抛出空指针异常
//三个参数:pred succ的左节点作为新节点的左节点,e 元素,succ succ本身作为新节点的右节点
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode; //succ 的左节点设置成 新节点
if (pred == null)
first = newNode; //首部添加,新节点为首节点
else
pred.next = newNode; //succ原左节点的右节点指向新节点
size++; //元素个数加1
modCount++; //变化次数加1
}
//删除首节点
private E unlinkFirst(Node<E> f) {
final E element = f.item; // f节点不为空,并且为首节点
final Node<E> next = f.next; // 记录首节点的右节点
f.item = null;
f.next = null; // 首节点元素属性置空,有利于垃圾回收
first = next; // 原首节点的右节点为新的首节点
if (next == null)
last = null; //链表中没有节点了,末节点为null
else
next.prev = null; //next为首节点后 左节点需为null
size--; //元素个数减1
modCount++; //变化次数加1
return element;//返回被删除元素
}
// 删除尾节点
private E unlinkLast(Node<E> l) {
// l 不为空,并且为尾节点
final E element = l.item; // 记录尾结点的元素项
final Node<E> prev = l.prev; // 记录尾结点的左节点
l.item = null;
l.prev = null; // 尾结点属性置为null,利于垃圾回收
last = prev; // 原尾结点的左节点为新的尾结点
if (prev == null)
first = null; //链表已经没有元素了,首节点为null
else
prev.next = null; //新尾结点的next 需要为 null
size--; //链表中元素个数减1
modCount++; //变化次数加1
return element; //返回被伤处元素
}
// 删除某节点
E unlink(Node<E> x) {
// x节点不能为null
final E element = x.item; // 记录删除节点的元素
final Node<E> next = x.next; // 记录删除节点的右节点
final Node<E> prev = x.prev; // 记录删除节点的左节点
if (prev == null) {
first = next; // 左节点为nul,删除节点为首节点,next做为新的首节点
} else {
prev.next = next; // 左节点指向右节点
x.prev = null; // 删除节点的左节点置为null,利于垃圾回收
}
if (next == null) {
last = prev; //next为null,删除的是尾结点,尾结点为prev
} else {
next.prev = prev; //删除节点的右节点指向伤处节点的左节点
x.next = null; //删除节点的next置为null,利于垃圾回收
}
x.item = null; //删除节点元素置为null,利于垃圾回收
size--; //链表中元素个数减1
modCount++; //变化次数加1
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);
}
// 从首部添加元素
public void addFirst(E e) {
linkFirst(e);
}
// 从尾部添加元素
public void addLast(E e) {
linkLast(e);
}
// 判断是否包含某个元素
public boolean contains(Object o) {
return indexOf(o) != -1;
}
// 返回链表中的元素个数
public int size() {
return size;
}
// 添加元素,默认从尾部添加
public boolean add(E e) {
linkLast(e);
return true;
}
// 删除某数据项
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 void clear() {
// 遍历所有都指向null
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; //元素个数为0
modCount++; //变化次数加1
}
// 获取某个索引的元素值
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)); //获取索引的节点并删除
}
// 返回某元素第一次在链表中的索引
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;
}
// 返回某元素在链表中的最后一个索引
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.
// 查看链表中是一个元素
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
// 返回第一个元素值,first为null,抛出异常
public E element() {
return getFirst();
}
// 删除头部节点,并返回头部节点的元素
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
// 删除头部节点,并返回元素,first为null时抛出异常
public E remove() {
return removeFirst();
}
// 尾部添加元素,并返回Boolean值
public boolean offer(E e) {
return add(e);
}
// Deque operations
// 首部添加元素,并返回Boolean值
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
// 尾部添加,并返回Boolean值
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();
}
// 删除某元素再链表中的第一个节点
public boolean removeFirstOccurrence(Object o) {
return remove(o);
}
// 删除某元素再链表中的最后一个
public boolean removeLastOccurrence(Object o) {
if (o == null) {
for (Node<E> x = last; x != null; x = x.prev) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = last; x != null; x = x.prev) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
// 返回 index到尾部的迭代器
public ListIterator<E> listIterator(int index) {
//检验索引是否合法
checkPositionIndex(index);
//返回迭代器
return new ListItr(index);
}
// 输出流
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden serialization magic
s.defaultWriteObject();
// Write out size
s.writeInt(size);
// Write out all elements in the proper order.
for (Node<E> x = first; x != null; x = x.next)
s.writeObject(x.item);
}
// 输入流
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden serialization magic
s.defaultReadObject();
// Read in size
int size = s.readInt();
// Read in all elements in the proper order.
for (int i = 0; i < size; i++)
linkLast((E)s.readObject());
}
@SuppressWarnings("unchecked")
private LinkedList<E> superClone() {
try {
return (LinkedList<E>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
// 返回一个浅克隆对象
public Object clone() {
LinkedList<E> clone = superClone();
// Put clone into "virgin" state
clone.first = clone.last = null;
clone.size = 0;
clone.modCount = 0;
// Initialize clone with our elements
for (Node<E> x = first; x != null; x = x.next)
clone.add(x.item);
return clone;
}
// 转为数组
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;
}
// 以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素)
// 返回的数组的运行时类型是指定数组的运行时类型
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
a = (T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);
int i = 0;
Object[] result = a;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
if (a.length > size)
a[size] = null;
return a;
}
迭代器,实现了ListIterator接口,可以进行双向迭代
/**
* 迭代器内部类
*/
private class ListItr implements ListIterator<E> {
private Node<E> lastReturned;//当前节点
private Node<E> next; //用于记录下一个节点
private int nextIndex; //用于记录当前索引
private int expectedModCount = modCount;
ListItr(int index) {
// assert isPositionIndex(index);
//返回index的值
next = (index == size) ? null : node(index);
//记录当前索引
nextIndex = index;
}
// 判断是否还有下一个元素
public boolean hasNext() {
return nextIndex < size;
}
// 从前往后遍历
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next; //记录当前节点的值
next = next.next; //记录下一节点
nextIndex++; //当前索引加1
//返回上个节点的值
return lastReturned.item;
}
// 从后往前遍历时,判断是否有前驱节点
public boolean hasPrevious() {
return nextIndex > 0;
}
// 从后往前遍历
public E previous() {
checkForComodification();
if (!hasPrevious())
throw new NoSuchElementException();
//从后往前遍历当前节点与下一节点相等
lastReturned = next = (next == null) ? last : next.prev;
nextIndex--;
return lastReturned.item;
}
// 获取当前节点索引
public int nextIndex() {
return nextIndex;
}
// 获取当前读音前驱节点索引
public int previousIndex() {
return nextIndex - 1;
}
public void remove() {
checkForComodification();
if (lastReturned == null)
throw new IllegalStateException();
Node<E> lastNext = lastReturned.next;
unlink(lastReturned);
if (next == lastReturned)
//删除首部时,next等于lastReturned,索引不变
next = lastNext;
else
nextIndex--;
lastReturned = null;
expectedModCount++;
}
public void set(E e) {
if (lastReturned == null)
throw new IllegalStateException();
checkForComodification();
lastReturned.item = e;
}
public void add(E e) {
checkForComodification();
lastReturned = null;
if (next == null)
linkLast(e);
else
linkBefore(e, next);
nextIndex++;
expectedModCount++;
}
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (modCount == expectedModCount && nextIndex < size) {
action.accept(next.item);
lastReturned = next;
next = next.next;
nextIndex++;
}
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}