上一篇:[集合类]源码解析6(Queue接口、AbstractQueue抽象类、Deque接口)
文章目录
1. AbstractSequentialList
该抽象类翻译成中文是,顺序列表。这是相对RandomAccess标志接口而言的,我们在[集合类] 源码解析1(Iterable、RandomAccess、Serializable、Cloneable)一文中分析了RandomAccess,其表示容器支持随机访问,这类容器会优先使用索引进行操作。而不支持随机访问的容器,通常使用迭代器进行操作。
AbstractSequentialList中实现了List中的一些基本操作,都是基于迭代器的实现,下面我们看一下源码。
/**
* 该类提供List接口的框架实现,以最小化由“顺序访问”数据存储(如链表)支持的实现该接口所需的工作。
* 对于随机访问数据(例如数组),应该优先使用AbstractList。
*
* 这个类与AbstractList类相反,因为它另外实现了list iterator的“随机访问”方法
* get(int index)、set(int index、E element)、add(int index、E element)和remove(int index)
* 而不是其他方式。
*
* 要实现一个列表,程序员只需继承这个类并为listIterator和size方法提供实现。
* 对于不可修改的列表,程序员只需实现列表迭代器的hasNext、next、hasPrevious、previous和index方法。
* 对于可修改的列表,程序员还应该实现列表迭代器的set方法。
* 对于可变大小的列表,程序员还应该实现列表迭代器的删除和添加方法。
*
* 按照集合接口规范中的建议,程序员通常应该提供一个void(无参数)和集合构造函数。
* 该类是Java集合框架的成员。
*/
public abstract class AbstractSequentialList<E> extends AbstractList<E> {
protected AbstractSequentialList() {
}
public E get(int index) {
try {
// 通过list迭代器实现
return listIterator(index).next();
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
// 如果list没有实现set方法,则抛出UnsupportedOperationException
public E set(int index, E element) {
try {
// 通过list迭代器实现
ListIterator<E> e = listIterator(index);
E oldVal = e.next();
e.set(element);
return oldVal;
} catch (NoSuchElementException exc) {
// 方便程序员定位异常
throw new IndexOutOfBoundsException("Index: "+index);
}
}
// 如果list没有实现add方法,则抛出UnsupportedOperationException
public void add(int index, E element) {
try {
// 通过list迭代器实现
listIterator(index).add(element);
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
// 如果list没有实现remove方法,则抛出UnsupportedOperationException
public E remove(int index) {
try {
// 通过list迭代器实现
ListIterator<E> e = listIterator(index);
E outCast = e.next();
e.remove();
return outCast;
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
// Bulk Operations
// 如果listIterator没有实现add方法,则抛出UnsupportedOperationException
public boolean addAll(int index, Collection<? extends E> c) {
try {
boolean modified = false;
ListIterator<E> e1 = listIterator(index);
Iterator<? extends E> e2 = c.iterator();
while (e2.hasNext()) {
e1.add(e2.next());
modified = true;
}
return modified;
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
// 返回list迭代器
public Iterator<E> iterator() {
return listIterator();
}
public abstract ListIterator<E> listIterator(int index);
}
2. LinkedList
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
可以看到LinkedList继承了AbstractSequentialList抽象类,说明LinkedList是一种顺序列表。
LinkedList实现了Cloneable和Serializable接口,我们之前分析过了,传送门:[集合类] 源码解析1(Iterable、RandomAccess、Serializable、Cloneable)
List接口我们之前也分析过了,传送门:[集合类]源码解析4(List接口和AbstractList抽象类)
Deque接口我们之前也分析过了,传送门:[集合类]源码解析6(Queue接口、AbstractQueue抽象类、Deque接口)
迭代器也分析过了,传送门:[集合类] 源码解析2(Iterator的实现)
下面我们看看LinkedList的具体实现。
1) Node
LinkedList是使用Node来存储数据的,我们在学习数据结构的时候已经对链表的结构有所了解。可以看出,LinkedList是双向链表,Node中除了item元素,还有next下一个节点引用,prev上一个节点引用。
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;
}
}
2) 属性
LinkedList有三个属性size、first、last,分别保存链表大小、第一个节点的引用、最后一个节点引用。
transient int size = 0;
transient Node<E> first;
transient Node<E> last;
3) 构造方法
LinkedList有两个构造方法,一个是空参的构造方法,另一个参数是集合,将集合中的元素添加到队列中。
public LinkedList() {
}
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
4) 工具方法
在LinkedList中,定义了一些工具方法,方便对链表进行操作。
// 将e构成新节点,添加到succ节点前面
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指向新节点
first = newNode;
else
// 否则,前一个节点的next指向新节点
pred.next = newNode;
size++;
modCount++;
}
// 将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指向新节点
last = newNode;
else
// 否则,后面节点的prev指向新节点
f.prev = newNode;
size++;
modCount++;
}
// 将e构成新节点,添加到链表末尾
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
// 链接前面的链表
if (l == null)
// 如果前面没有节点,first指向新节点
first = newNode;
else
// 否则,前一个节点的next指向新节点
l.next = newNode;
size++;
modCount++;
}
// x节点脱离链表(删除x节点,返回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) {
// 如果x是第一个节点
first = next;
} else {
prev.next = next;
x.prev = null;
}
// 修改后一个节点的指向
if (next == null) {
// 如果x是最后一个节点
last = prev;
} else {
next.prev = prev;
x.next = null;
}
// 置空,方便GC
x.item = null;
size--;
modCount++;
return element;
}
// 头节点脱离链表(删除头节点,返回头节点的元素值)
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指向
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指向
last = prev;
// 修改上一个节点指向
if (prev == null)
// 如果上一个节点为空
first = null;
else
prev.next = null;
size--;
modCount++;
return elemen;
}
// 查找第index个元素
Node<E> node(int index) {
// assert isElementIndex(index);
// 如果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;
}
}
// 判断index合法性,查找、修改使用,不能等于size
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}
// 判断index合法性,添加使用,可以等于size
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size;
}
// 越界信息
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
// 检查index合法性,不合法抛出异常
private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
// 检查index合法性,不合法抛出异常
private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
5) List方法
(1) 添加方法
// 添加到链表末尾
public boolean add(E e) {
linkLast(e);
return true
}
// 添加到index位置
public void add(int index, E element) {
// 判断index合法性
checkPositionIndex(index);
if (index == size)
// 如果是最后一个位置,直接添加到末尾
linkLast(element);
else
// 否则,添加到第index节点前面
linkBefore(element, node(index));
}
// 添加到链表末尾
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
// 判断index合法性
checkPositionIndex(index);
// 转化为数组,返回副本,防止外部对c进行更改,从而影响链表
Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false;
// pred是插入位置的前一个节点,succ是插入位置节点
Node<E> pred, succ;
if (index == size) {
// 插入到最后
succ = null;
pred = last;
} else {
// 插入到index位置
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;
} // 执行完后pred指向添加的最后一个元素
// 将后面链表接上
if (succ == null) {
// 插入到最后,对应index == size情况,直接修改last指向
last = pred;
} else {
// 将后面的链表接上
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
(2) 删除方法
// 清空所有元素
public void clear() {
// 清除所有链接,方便GC
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++;
}
// 删除第index个节点
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
// 删除第一个出现的o对象,没有找到返回false
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;
}
(3) 修改方法
public E set(int index, E element) {
checkElementIndex(index);
// 首先找到目标节点
Node<E> x = node(index);
E oldVal = x.item;
// 修改值
x.item = element;
return oldVal;
}
(4) 查找方法
// 判断链表中是否含有元素为o的节点
public boolean contains(Object o) {
return indexOf(o) != -1;
}
// 链表节点个数
public int size() {
return size;
}
// 获取第index节点的元素值
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
// 从头开始找,元素值为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;
}
// 从尾开始找,元素值为o的索引,没找到返回-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;
}
// 返回数组副本
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;
}
public <T> T[] toArray(T[] a) {
// 判断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;
// 如果a数组没有用完,最后一个元素置null
if (a.length > size)
a[size] = null;
return a;
}
6) Deque方法
(1) 添加方法
// 添加到链表头
public void addFirst(E e) {
linkFirst(e);
}
// 添加到链表尾
public void addLast(E e) {
linkLast(e);
}
// 入队
public boolean offer(E e) {
return add(e);
}
// 队头入队
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
// 队尾入队
public boolean offerLast(E e) {
addLast(e);
return true;
}
// 入栈
public void push(E e) {
addFirst(e);
}
(2) 删除方法
// 出队
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
// 队头出队
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 E pop() {
return removeFirst();
}
// 删除链表头节点
public E remove() {
return removeFirst();
}
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);
}
// 删除第一个等于o的节点
public boolean removeFirstOccurrence(Object o) {
return remove(o);
}
// 删除最后一个等于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;
}
(3) 查找方法
// 获取第一个元素
public E element() {
return getFirst();
}
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 peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
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;
}
来源:CSDN
作者:nsn_huang
链接:https://blog.csdn.net/sougou_1323/article/details/103482348