1LinkedListの概要
1 LinkedListはAbstractSequentialListを継承し、インターフェースListを実装します。これは、二重にリンクされたリストの実現です。
2 LinkedListは、インターフェースDequeを実装します。dequeが実装されていることを示します。FIFOにすることができます。LIFO(後入先出)にすることもでき
ます。3LinkedListは、CloneableおよびSerializableインターフェースを実装し、クローンを作成できることを示します。シリアル化することもできます。
2物件紹介
/**
* 元素的个数
*/
transient int size = 0;
/**
* 指向第一个结点的指针
*/
transient Node<E> first;
/**
* 指向最后一个结点的指针
*/
transient Node<E> last;
3構造
//默认的构造器
public LinkedList() {
}
/**
* 构造一个包含元素的集合。
*/
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
4リンクリストノードクラス構造
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;
}
}
5ソースコードの解釈
5.1 E getFirst()最初の要素を取得します
/**
* 获取第一个元素。直接将头指针赋值给当前结点,然后当前结点返回存储的数据item。如果为空,则报NoSuchElementException异常。
*/
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
5.2 E getLast()最後の要素を取得します
/**
* 获取最后一个元素。直接将尾指针赋值给当前结点,然后当前结点返回存储的数据item。如果为空,则报NoSuchElementException异常。
*/
public E getLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return l.item;
}
5.3 E removeFirst()最初の要素を削除します
/**
* 删除第一个元素。直接将头指针赋值给当前结点,然后解除结点之间的联系。调用unlinkFirst()方法接触引用
*/
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
unlinkFirst()メソッドを見てみましょう。
private E unlinkFirst(Node<E> f) {
// 获取删除结点的数据,作为最后的返回
final E element = f.item;
//获取删除结点的下一个结点
final Node<E> next = f.next;
//将删除结点的数据和后继设置为null,有利于垃圾回收
f.item = null;
f.next = null; // help GC
//将删除结点的后继设置为头结点。
first = next;
//设置前驱为空。然后元素个数-1
if (next == null)
last = null;
else
next.prev = null;
size--;
//集合修改的次数。在迭代器迭代集合的时候使用
modCount++;
return element;
}
5.4 E removeLast()は最後の要素を削除します
public E removeLast() {
//将尾结点赋值给当前结点,然后解除尾结点的引用。
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
unlinkLastを呼び出して、エンドノード間の参照を解放します。このメソッドの実装を見てみましょう。
private E unlinkLast(Node<E> l) {
final E element = l.item;
//获取删除结点的前驱
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // 方法GC
//将前驱设置为尾结点
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
}
5.5 addFirst(E e)、addLast(E e)要素の追加
//头插
public void addFirst(E e) {
linkFirst(e);
}
//尾插
public void addLast(E e) {
linkLast(e);
}
linkFirstとlinkLastをそれぞれ呼び出して達成します。これらの2つの方法を見てみましょう。
private void linkFirst(E e) {
//获取头结点
final Node<E> f = first;
//创建结点。设置前驱为null。后继为f。也就是插入之前的头结点
final Node<E> newNode = new Node<>(null, e, f);
//将创建的新节点赋值给头结点。
first = newNode;
if (f == null)
//如果当前结点为空,那么新结点就是尾结点。
last = newNode;
else
//将新节点设置为当前结点的前驱
f.prev = newNode;
//元素个数+1
size++;
modCount++;
}
/**
* Links e as last element.
*/
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++;
}
5.6ブールcontains(Object o)要素を含めるかどうかを決定する
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
indexOf()メソッドを呼び出して達成します。内部メソッドを見てみましょう。
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 {
//遍历链表。如果当前对象equals结点元素,返回索引。
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}
5.7 int size()リンクリストの長さを取得します
public int size() {
return size;
}
5.8ブールadd(E e)要素の追加
デフォルトはテールプラグです。
public boolean add(E e) {
linkLast(e);
return true;
}
5.9ブール値remove(Object 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 {
//元素不为空的情况
//遍历链表,找到元素,然后解除链表结点之间的引用。调用了unlink来解除
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
unlinkメソッドは、要素間の参照を削除します。この方法を見てください。
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;
//元素个数-1
size--;
modCount++;
return element;
}
5.10 clear()はコレクションをクリアします。
各ノードをトラバースしてから、すべてのノード要素を空に設定します。ノードを空に設定します。コレクション要素の数は0に設定されます
public void clear() {
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++;
}