前言
本篇主要记录Java集合类中LinkedList的用法、结构以及部分实现。
LinkedList简介
LinkedList
是一个实现了List接口和Deque接口的双端链表。 它实现了的其他接口还有Cloneable
, java.io.Serializable
,另外他也继承了AbstractSequentialList
抽象类。
LinkedList底层的链表结构使它支持高效的插入和删除操作,实现了Deque接口,使得LinkedList类也具有队列的特性;
LinkedList不是线程安全的,如果想使LinkedList变成线程安全的,可以调用静态类Collections
类中的synchronizedList
方法:
1 | List list=Collections.synchronizedList(new LinkedList(...)); |
内部结构分析
LinkedList的内部结构如下图所示:
Node就是链表中的节点。那么LinkedList类中的一个内部静态私有类Node就很好理解了:
1 | private static class Node<E> { |
这个类就代表双端链表的节点Node。这个类有三个属性,分别是前驱节点,本节点的值,后继结点。
LinkedList源码分析
下面介绍一些LinkedList类的一些API的实现。
构造方法
空构造方法:
1 | public LinkedList() { |
用已有的集合创建链表的构造方法:
1 | public LinkedList(Collection<? extends E> c) { |
add方法
add(E e) 方法:将元素添加到链表尾部
1 | public boolean add(E e) { |
1 | /** |
**add(int index,E e)**:在指定位置添加元素
1 | public void add(int index, E element) { |
linkBefore方法需要给定两个参数,一个插入节点的值,一个指定的node,所以我们又调用了Node(index)去找到index对应的node
addAll(Collection c ):将集合插入到链表尾部
1 | public boolean addAll(Collection<? extends E> c) { |
addAll(int index, Collection c): 将集合从指定位置开始插入
1 | public boolean addAll(int index, Collection<? extends E> c) { |
上面可以看出addAll方法通常包括下面四个步骤:
- 检查index范围是否在size之内
- toArray()方法把集合的数据存到对象数组中
- 得到插入位置的前驱和后继节点
- 遍历数据,将数据插入到指定位置
addFirst(E e): 将元素添加到链表头部
1 | public void addFirst(E e) { |
1 | private void linkFirst(E e) { |
addLast(E e): 将元素添加到链表尾部,与 add(E e) 方法一样
1 | public void addLast(E e) { |
根据位置取数据的方法
get(int index): 根据指定索引返回数据
1 | public E get(int index) { |
1 | Node<E> node(int index) { |
获取头节点(index=0)数据方法:
1 | public E getFirst() { |
区别:
getFirst(),element(),peek(),peekFirst()
这四个获取头结点方法的区别在于对链表为空时的处理,是抛出异常还是返回null,其中getFirst() 和element() 方法将会在链表为空时,抛出异常。
element()方法的内部就是使用getFirst()实现的。它们会在链表为空时,抛出NoSuchElementException
异常。
获取尾节点(index=-1)数据方法:
1 | public E getLast() { |
两者区别:
getLast() 方法在链表为空时,会抛出NoSuchElementException,而peekLast() 则不会,只是会返回 null。
根据对象得到索引的方法
int indexOf(Object o): 从头遍历找
1 | public int indexOf(Object o) { |
int lastIndexOf(Object o): 从尾遍历找
1 | public int lastIndexOf(Object o) { |
检查链表是否包含某对象的方法
contains(Object o): 检查对象o是否存在于链表中
1 | public boolean contains(Object o) { |
删除方法
remove() ,removeFirst(),pop(): 删除头节点
1 | public E pop() { |
removeLast(),pollLast(): 删除尾节点
1 | public E removeLast() { |
区别: removeLast()在链表为空时将抛出NoSuchElementException,而pollLast()方法返回null。
remove(Object o): 删除指定元素
1 | public boolean remove(Object o) { |
当删除指定对象时,只需调用remove(Object o)即可,不过该方法一次只会删除一个匹配的对象,如果删除了匹配对象,返回true,否则false。
unlink(Node<E> x)
方法:
1 | E unlink(Node<E> x) { |
**remove(int index)**:删除指定位置的元素
1 | public E remove(int index) { |
一些API
返回值 | 方法参数及作用描述 |
---|---|
boolean |
add(E e) 将指定的元素追加到此列表的末尾。 |
void |
add(int index, E element) 在此列表中的指定位置插入指定的元素。 |
boolean |
addAll(Collection<? extends E> c) 按照指定集合的迭代器返回的顺序将指定集合中的所有元素追加到此列表的末尾。 |
boolean |
addAll(int index, Collection<? extends E> c) 将指定集合中的所有元素插入到此列表中,从指定的位置开始。 |
void |
addFirst(E e) 在该列表开头插入指定的元素。 |
void |
addLast(E e) 将指定的元素追加到此列表的末尾。 |
void |
clear() 从列表中删除所有元素。 |
Object |
clone() 返回此 LinkedList 的浅版本。 |
boolean |
contains(Object o) 如果此列表包含指定的元素,则返回 true 。 |
Iterator<E> |
descendingIterator() 以相反的顺序返回此deque中的元素的迭代器。 |
E |
element() 检索但不删除此列表的头(第一个元素)。 |
E |
get(int index) 返回此列表中指定位置的元素。 |
E |
getFirst() 返回此列表中的第一个元素。 |
E |
getLast() 返回此列表中的最后一个元素。 |
int |
indexOf(Object o) 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。 |
int |
lastIndexOf(Object o) 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。 |
ListIterator<E> |
listIterator(int index) 从列表中的指定位置开始,返回此列表中元素的列表迭代器(按适当的顺序)。 |
boolean |
offer(E e) 将指定的元素添加为此列表的尾部(最后一个元素)。 |
boolean |
offerFirst(E e) 在此列表的前面插入指定的元素。 |
boolean |
offerLast(E e) 在该列表的末尾插入指定的元素。 |
E |
peek() 检索但不删除此列表的头(第一个元素)。 |
E |
peekFirst() 检索但不删除此列表的第一个元素,如果此列表为空,则返回 null 。 |
E |
peekLast() 检索但不删除此列表的最后一个元素,如果此列表为空,则返回 null 。 |
E |
poll() 检索并删除此列表的头(第一个元素)。 |
E |
pollFirst() 检索并删除此列表的第一个元素,如果此列表为空,则返回 null 。 |
E |
pollLast() 检索并删除此列表的最后一个元素,如果此列表为空,则返回 null 。 |
E |
pop() 从此列表表示的堆栈中弹出一个元素。 |
void |
push(E e) 将元素推送到由此列表表示的堆栈上。 |
E |
remove() 检索并删除此列表的头(第一个元素)。 |
E |
remove(int index) 删除该列表中指定位置的元素。 |
boolean |
remove(Object o) 从列表中删除指定元素的第一个出现(如果存在)。 |
E |
removeFirst() 从此列表中删除并返回第一个元素。 |
boolean |
removeFirstOccurrence(Object o) 删除此列表中指定元素的第一个出现(从头到尾遍历列表时)。 |
E |
removeLast() 从此列表中删除并返回最后一个元素。 |
boolean |
removeLastOccurrence(Object o) 删除此列表中指定元素的最后一次出现(从头到尾遍历列表时)。 |
E |
set(int index, E element) 用指定的元素替换此列表中指定位置的元素。 |
int |
size() 返回此列表中的元素数。 |
Spliterator<E> |
spliterator() 在此列表中的元素上创建late-binding和故障快速 Spliterator 。 |
Object[] |
toArray() 以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。 |
<T> T[] |
toArray(T[] a) 以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。 |
最后
本文阐述了Java集合类LinkedList的内部结构以及部分源码实现,并总结了该集合的一些常用方法。