2024全网最全LinkedList源码专题(25秋招走起~)

本文主要对Collection - LinkedList进行源码解析。@pdai
Collection - LinkedList源码解析
概述
LinkedList实现
底层数据结构
构造函数
getFirst(), getLast()
removeFirst(), removeLast(), remove(e), remove(index)
add()
addAll()
clear()
Positional Access 方法
查找操作
Queue 方法
Deque 方法
参考
# 概述
LinkedList同时实现了List接口和Deque接口,也就是说它既可以看作一个顺序容器,又可以看作一个队列(Queue),同时又可以看作一个栈(Stack)。这样看来,LinkedList简直就是个全能冠军。当你需要使用栈或者队列时,可以考虑使用LinkedList,一方面是因为Java官方已经声明不建议使用Stack类,更遗憾的是,Java里根本没有一个叫做Queue的类(它是个接口名字)。关于栈或队列,现在的首选是ArrayDeque,它有着比LinkedList(当作栈或队列使用时)有着更好的性能。
LinkedList的实现方式决定了所有跟下标相关的操作都是线性时间,而在首段或者末尾删除元素只需要常数时间。为追求效率LinkedList没有实现同步(synchronized),如果需要多个线程并发访问,可以先采用Collections.synchronizedList()方法对其进行包装。
# LinkedList实现
# 底层数据结构
LinkedList底层通过双向链表实现,本节将着重讲解插入和删除元素时双向链表的维护过程,也即是之间解跟List接口相关的函数,而将Queue和Stack以及Deque相关的知识放在下一节讲。双向链表的每个节点用内部类Node表示。LinkedList通过first和last引用分别指向链表的第一个和最后一个元素。注意这里没有所谓的哑元,当链表为空的时候first和last都指向null。
其中Node是私有的内部类:
# 构造函数
# getFirst(), getLast()
获取第一个元素, 和获取最后一个元素:
# removeFirst(), removeLast(), remove(e), remove(index)
remove()方法也有两个版本,一个是删除跟指定元素相等的第一个元素remove(Object o),另一个是删除指定下标处的元素remove(int index)。
删除元素 - 指的是删除第一次出现的这个元素, 如果没有这个元素,则返回false;判断的依据是equals方法, 如果equals,则直接unlink这个node;由于LinkedList可存放null元素,故也可以删除第一次出现null的元素;
remove(int index)使用的是下标计数, 只需要判断该index是否有元素即可,如果有则直接unlink这个node。
删除head元素:
删除last元素:
# add()
add()方法有两个版本,一个是add(E e),该方法在LinkedList的末尾插入元素,因为有last指向链表末尾,在末尾插入元素的花费是常数时间。只需要简单修改几个相关引用即可;另一个是add(int index, E element),该方法是在指定下表处插入元素,需要先通过线性查找找到具体位置,然后修改相关引用完成插入操作。
add(int index, E element), 当index==size时,等同于add(E e); 如果不是,则分两步: 1.先根据index找到要插入的位置,即node(index)方法;2.修改引用,完成插入操作。
上面代码中的node(int index)函数有一点小小的trick,因为链表双向的,可以从开始往后找,也可以从结尾往前找,具体朝那个方向找取决于条件index < (size >> 1),也即是index是靠近前端还是后端。从这里也可以看出,linkedList通过index检索元素的效率没有arrayList高。
# addAll()
addAll(index, c) 实现方式并不是直接调用add(index,e)来实现,主要是因为效率的问题,另一个是fail-fast中modCount只会增加1次;
# clear()
为了让GC更快可以回收放置的元素,需要将node之间的引用关系赋空。
# Positional Access 方法
通过index获取元素
将某个位置的元素重新赋值:
将元素插入到指定index位置:
删除指定位置的元素:
其它位置的方法:
# 查找操作
查找操作的本质是查找元素的下标:
查找第一次出现的index, 如果找不到返回-1;
查找最后一次出现的index, 如果找不到返回-1;
# Queue 方法
# Deque 方法

Java复制代码

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

/**

*

* <p>This method is equivalent to {@link #addFirst}.

*

* @param e the element to push

* @since 1.6

*/

public void push(E e) {

addFirst(e);

}

/**

* Pops an element from the stack represented by this list. In other

* words, removes and returns the first element of this list.

*

* <p>This method is equivalent to {@link #removeFirst()}.

*

* @return the element at the front of this list (which is the top

* of the stack represented by this list)

* @throws NoSuchElementException if this list is empty

* @since 1.6

*/

public E pop() {

return removeFirst();

}

/**

* Removes the first occurrence of the specified element in this

* list (when traversing the list from head to tail). If the list

* does not contain the element, it is unchanged.

*

* @param o element to be removed from this list, if present

* @return {@code true} if the list contained the specified element

* @since 1.6

*/

public boolean removeFirstOccurrence(Object o) {

return remove(o);

}

/**

* Removes the last occurrence of the specified element in this

* list (when traversing the list from head to tail). If the list

* does not contain the element, it is unchanged.

*

* @param o element to be removed from this list, if present

* @return {@code true} if the list contained the specified element

* @since 1.6

*/

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;

}

# 参考
●Java LinkedList源码剖析 结合源码对LinkedList进行讲解 http://www.cnblogs.com/CarpenterLee/p/5457150.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值