linkedlist是基于链表的
transient int size = 0;//大小
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;
}
}
add()方法
public boolean add(E e) {
linkLast(e);//在最后插入新节点
return true;
}
public void add(int index, E element) {
checkPositionIndex(index);
if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}
插入尾节点
public void addLast(E e) {
linkLast(e);
}
void linkLast(E e) {
final Node<E> l = last; //新建节点l
final Node<E> newNode = new Node<>(l, e, null); //新建newNode节点,元素是e,前一个节点是l
last = newNode;//linkLast方法新建节点顺序往后加,所以newNode作为尾节点
if (l == null)
first = newNode; //如果尾节点l是null
else
l.next = newNode; //否则,newNode作为l的下一个节点
size++; //size+1
modCount++;//修改计数器+1
}
linkFirst()插入一个头结点
public void addFirst(E e) {
linkFirst(e);
}
private void linkFirst(E e) {
final Node<E> f = first;//f赋值之前的头结点
final Node<E> newNode = new Node<>(null, e, f); //新建节点把之前的头结点作为新建节点的后一个节点
first = newNode;//对头结点赋值newNode
if (f == null)
last = newNode;
else
f.prev = newNode;//之前头结点的前一个节点赋值为newNode
size++;
modCount++;
}
在某个节点前插入
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;//succ节点的前一个节点赋值给新建节点pred
final Node<E> newNode = new Node<>(pred, e, succ); 新建newNode 节点,newNode 的后一个节点是succ,前一个节点是pred,元素是e,就是e节点
succ.prev = newNode;//succ的前一个节点是newNode
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
删掉头结点
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; //获取f节点的元素
final Node<E> next = f.next; //获取f节点的后一个节点
f.item = null; //f节点元素置空
f.next = null; // help GC
first = next; //将f的后一个节点当做头结点
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
删掉尾节点差不多
删掉某一个节点
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
public boolean remove(Object o) {
if (o == null) { //o可以为空,linkedList可以存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; //获取x的元素
final Node<E> next = x.next; //获取x的后一个节点
final Node<E> prev = x.prev; //获取x的前一个节点
if (prev == null) {//如果prev == null说明x是头结点,删掉X后,头节点变成next
first = next;
} else {
prev.next = next;//x的前一个节点的后一个节点给next,因为x要被x删掉了
x.prev = null; //x的前一个节点的后一个节点本来是指向x的,x没了要置空,删掉对x的引用,要GC回收
}
if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
}
//以上是对X的前一个节点和后一个节点的处理(pred和next)
x.item = null; //对X的值置空,彻底将X置空和X的引用置空,等待GC
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 boolean contains(Object o) {
return indexOf(o) != -1;
}
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 boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index);//检查index是否超出范围
Object[] a = c.toArray();//把c转化成普通数组
int numNew = a.length; //a的长度
if (numNew == 0) //numNew =0代表c是空没得插入
return false;
Node<E> pred, succ;
if (index == size) {//index == size代表正好在结尾插入
succ = null;
pred = last;//pred就是尾节点了
} else {
succ = node(index);//正好在succ前插入
pred = succ.prev;//pred就是succ的前一个节点
}
for (Object o : a) {//循环数组
@SuppressWarnings("unchecked") E e = (E) o;//对e赋值
Node<E> newNode = new Node<>(pred, e, null);//新建节点newNode
if (pred == null)//如果是头结点,newNode作为头结点,只有数组的第一个元素有可能走这一步
first = newNode;
else
pred.next = newNode;//因为是在succ后插入,pred是succ的前一个节点,所以pred.next是指向新节点的
pred = newNode;
}
if (succ == null) {
last = pred;
} else {
pred.next = succ;//新加入的元素的最后一个元素的后一个节点是next
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
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;
}
返回指定位置的元素
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) { //index < size / 2
Node<E> x = first;
for (int i = 0; i < index; i++)//链表结构不能像数组一样用下标,只能一个一个顺序找,当index在前一半的时候正向查找
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)//当index在后一半的时候反向查找,从最后开始倒序查
x = x.prev;
return x;
}
}
清空
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++;
}
获取某个元素的值
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
set
public E set(int index, E element) {
checkElementIndex(index);
Node<E> x = node(index);//先找到节点
E oldVal = x.item;
x.item = element;
return oldVal;
}
返回元素位置,可以看出元素可以为null
//从前查
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;
}
push
public void push(E e) {
addFirst(e);
}
pop
public E pop() {
return removeFirst();
}