继承结构
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
继承了AbstractSequentialList,实现了List接口,Deque接口和java.io.Serializable接口。
可以用来实现队列!
Node结构
存储当前元素,前一个节点,和后一个节点。
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 LinkedList() {
}
//集合参数构造函数
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);//把集合中的所有节点加入到list中
}
添加元素
- add(E e)
public boolean add(E e) {
linkLast(e);
return true;
}
//把节点加入链表末尾
void linkLast(E e) {
//新建node节点保存last节点
final Node<E> l = last;
//新建node节点,pre指向list中的last节点,当前元素为e,next置空。
final Node<E> newNode = new Node<>(l, e, null);
//last指向新节点
last = newNode;
//如果节点l为空(即链表为空),把newNode赋值给first
if (l == null)
first = newNode;
//如果不为空,将list之前的last节点,也就是现在的l节点的next指向newNode,链表就连接完成了。
else
l.next = newNode;
size++;
modCount++;
}
- add(index,E element)
这个函数在刷题的时候有用到,当时觉得很神奇,怎么像ArrayList一样可以按索引插入呢,原来就是从头或者从尾开始遍历……
public void add(int index, E element) {
//判断索引位置是否合法,不合法就抛异常,合法就继续。
checkPositionIndex(index);
//如果索引和链表长度一致,那就在末尾添加元素
if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
//新建节点保存index位置的前一个节点
final Node<E> pred = succ.prev;
//新建节点,pre指向原来index位置的前一个节点,当前元素为e,next指向原来index位置的元素。
final Node<E> newNode = new Node<>(pred, e, succ);
//之后的操作和add一样,就是把链表连起来。
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
怎么知道索引为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;
}
}
- addAll(int index, Collection<? extends E> c)
这个在有参构造函数时也调用了
public boolean addAll(int index, Collection<? extends E> c) {
//检查index合法性
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;
}