文章目录
-
- 1、LinkedList 简述
- 2、LinkedList 类图
- 2.1、LinkedList 内部结构
- 3、LinkedList 成员变量
- 4、LinkedList 构造函数
- 5、LinkedList 方法
-
- 5.1、LinkedList 获取元素
- 5.2、LinkedList 增加元素
-
- 5.2.1、public boolean add(E e) 等价 addLast
- 5.2.2、public void add(int index, E element)
- 5.2.3、public void addFirst(E e)
- 5.2.4、public void addLast(E e) 等价 add
- 5.2.5、public boolean addAll(Collection<? extends E> c)
- 5.2.6、public boolean addAll(int index, Collection<? extends E> c)
- 5.2.7、public boolean offer(E e) 等价于 add
- 5.2.8、public boolean offerFirst(E e) 等价于 addFirst(E e)
- 5.2.9、public boolean offerLast(E e) 等价于 addLast(E e)
- 5.2.10、public void push(E e) 等价于 addFirst(E e)
- 5.3、LinkedList 删除元素
-
- 5.3.1、public E remove()
- 5.3.2、public E remove(int index)
- 5.3.3、public boolean remove(Object o)
- 5.3.4、public E removeFirst()
- 5.3.5、public E removeLast()
- 5.3.6、public boolean removeFirstOccurrence(Object o)
- 5.3.7、public boolean removeLastOccurrence(Object o)
- 5.3.8、public E poll()
- 5.3.9、public E pollFirst()
- 5.3.10、public E pollLast()
- 5.3.11、public E pop() 等价于 removeFirst()
- 5.3.12、public void clear()
- 5.4、LinkedList 其它方法
-
- 5.4.1、public boolean contains(Object o)
- 5.4.2、public int size()
- 5.4.3、public E set(int index,E element)
- 5.4.4、public ListIterator listIterator(int index)
- 5.4.5、public Iterator descendingIterator()
- 5.4.6、public Object clone()
- 5.4.7、public Object[] toArray()
- 5.4.8、public T[] toArray(T[] a)
- 5.4.9、public Spliterator spliterator()
1、LinkedList 简述
1)Java LinkedList是List和Deque接口的实现。
2)在内部,LinkedList 是采用双向链表实现的,它包含一个很重要的内部类 Node。Node是双向链表节点所对应的数据结构,它包括的属性有:当前节点所包含的值,上一个节点,下一个节点。
3)它支持重复元素,并且可以添加任意数量的null元素。
4)它以插入顺序存储或维护它的元素。
5)它不是线程安全的,我们可以使用Collections.synchronizedList(new LinkedList(…));方法创建一个同步的链表。
6)在Java应用中,LinkedList 可以用作List,LIFO(后进先出)的栈或FIFO(先进先出)的队列。
7)它没有实现RandomAccess接口。 所以我们只能按顺序访问元素。 它不支持随机访问元素。
8)当我们尝试从 LinkedList 访问元素时,根据元素可用的位置搜索该元素从LinkedList的开头或结尾开始。
9)我们可以使用ListIterator来迭代LinkedList元素。
10)从LinkedList的实现方式中可以发现,它不存在LinkedList容量不足的问题。
11)LinkedList 的克隆函数(clone()),是将全部元素克隆到一个新的LinkedList对象中。
12)LinkedList 实现java.io.Serializable。当写入到输出流时,先写入“容量”,再依次写入“每一个节点保护的值”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。
13)由于LinkedList实现了Deque,而Deque接口定义了在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(null 或 false,具体取决于操作)
14)从Java 8开始,我们可以将LinkedList 转换为 Stream,反之亦然。
15)Java 9 添加了几个工厂方法来创建一个Immutable LinkedList。
2、LinkedList 类图
众所周知,Java LinkedList是List实现类之一。
java.util.LinkedList 继承了 AbstractSequentialList 并实现了List , Deque , Cloneable 以及Serializable 接口
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
2.1、LinkedList 内部结构
LinkedList内部结构是一个双向链表
每一个节点都是一个Node 对象,由三个元素组成
private static class Node<E> {
// E类型的值item
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;
}
}
3、LinkedList 成员变量
3.1、size 链表的节点数量
初始化链表的长度为0
transient int size = 0;
3.2、first 指向第一个节点的指针
/**
* 指向第一个节点的指针
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first;
3.3、last 指向最后一个节点的指针
/**
* 指向最后一个节点的指针。
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node<E> last;
4、LinkedList 构造函数
4.1、LinkedList()
构造一个空列表。
public LinkedList() {}
4.2、LinkedList(Collection<? extends E> c)
/**
* 按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表。
*
* @param c 要将其元素放入此列表的集合
* @throws NullPointerException 如果指定集合为null
*/
public LinkedList(Collection<? extends E> c) {
this();
//使用addAll方法,实际上就是遍历c并且采用头插法进行双向链表插入值。
addAll(c);
}
5、LinkedList 方法
由于LinkedList实现了Deque,而Deque接口定义了在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(null 或 false,具体取决于操作)
操作 | 头部元素 | 尾部元素 | ||
返回值 | 抛出异常 | 特殊值 | 抛出异常 | 特殊值 |
插入 | addFirst(e) | offerFirst(e) | addLast(e) | offerLast(e) |
移除 | removeFirst() | pollFirst() | removeLast() | pollLast() |
检索 | getFirst() | peekFirst() | getLast() | peekLast() |
LinkedList 可以作为 FIFO(先进先出)的队列,作为FIFO的队列时,下面的方法是等价的
队列方法 | 等价方法 |
---|---|
add(e) | addLast(e) |
offer(e) | offerLast(e) |
remove() | removeFirst() |
poll() | pollFirst() |
element() | getFirst() |
peek() | peekFirst() |
LinkedList 可以作为 LIFO(后进先出)的栈,作为LIFO的栈时,下面的方法是等价的
栈方法 | 等价方法 |
---|---|
push(e) | addFirst(e) |
pop() | removeFirst() |
peek() | peekFirst() |
5.1、LinkedList 获取元素
5.1.1、public E get(int index)
获取指定索引处节点的元素,首先对指定索引进行越界检查,如果未越界返回相应位置node节点的元素;否则,抛出 IndexOutOfBoundsException 异常
/**
* 返回此列表中指定位置的元素。
*
* @param index 要返回的元素的索引值
* @return 列表中指定位置的元素
* @throws IndexOutOfBoundsException
*/
public E get(int index) {
//索引越界检查
checkElementIndex(index);
return node(index).item;
}
private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 判断参数是否是现有元素的索引。
*/
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}
/**
* 构造一个IndexOutOfBoundsException详细消息。
*
*/
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
/**
* 返回指定元素索引处的(非null)节点。
*/
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