linux c list源码详解,List源码解析之LinkedList 源码分析

LinkedList简介

实现了List和Deque接口,既可以看作一个顺序容器,又可以看作一个队列(Queue),同时又可以看作一个栈(Stack)(处理栈和队列问题,首选ArrayDeque,它的性能比LinkedList作栈和队列使用好很多)。

LinkedList是一种双向链表,通过first和last引用分别指向链表的第一个和最后一个元素。

LinkedList是非线程安全的,也就是说它不是同步的,适合单线程环境使用;需要多个线程并发访问,可以先采用Collections.synchronizedList()方法对其进行包装。

LinkedList实现了Serializable接口,因此它支持序列化,能够通过序列化传输,实现了Cloneable接口,能被克隆。

属性和构造函数

transient int size = 0; //数量

transient Node first; //首节点

transient Node last; //尾节点

private static classNode{

E item;

Node next;

Node prev;

Node(Node prev, E element, Node next) {

this.item = element;

this.next = next;

this.prev = prev;

}

}

/*** Constructs an empty list.*/

publicLinkedList(){

}

/*** 构造一个包含指定collection 的元素的列表,这些元素按照* 该collection 的迭代器返回它们的顺序排列的*/

publicLinkedList(Collection<?extendsE> c){

this();

addAll(c);

}

存储

set(int index, E element)

// 用指定的元素替代此列表中指定位置上的元素,并返回以前位于该位置上的元素

publicEset(intindex, E element){

checkElementIndex(index);

Node x = node(index);

E oldVal = x.item;

x.item = element;

return oldVal;

}

add(E e)

// 添加指定元素到链表尾部,花费时间为常数时间

publicbooleanadd(E e){

linkLast(e);

return true;

}

/*** Links e as last element.链接e作为最后一个元素,默认向表尾节点加入新的元素*/

voidlinkLast(E e){

final Node l = last;

final Node newNode = new Node<>(l, e, null); // 当插入数据量大时,生成对象比较耗时

last = newNode;

if (l == null)

first = newNode;

else

l.next = newNode;

size++;

modCount++;

}

add(int index, E element)

// 在指定位置插入

publicvoidadd(intindex, E element){

checkPositionIndex(index);

if (index == size)

linkLast(element);

else

linkBefore(element, node(index));

}

// 下标位置越界检查

privatevoidcheckPositionIndex(intindex){

if (!isPositionIndex(index))

throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

}

/*** Inserts element e before non-null Node succ.*/

voidlinkBefore(E e, Node succ){

// assert succ != null;

final Node pred = succ.prev;

final Node newNode = new Node<>(pred, e, succ);

succ.prev = newNode;

if (pred == null)

first = newNode;

else

pred.next = newNode;

size++;

modCount++;

}

addAll(Collection extends E> c)

// 按照指定collection 的迭代器所返回的元素顺序,将该collection 中的所有元素添加到此列表的尾部

publicbooleanaddAll(Collection<?extendsE> c){

return addAll(size, c);

}

// 具体看源码吧

读取

get(int index)

// 返回指定下标的元素

publicEget(intindex){

checkElementIndex(index);

return node(index).item;

}

删除

1.先找到要删除元素的引用,2.修改相关引用,完成删除操作

remove(int index)

使用下标计数

// 删除指定位置的元素,并返回

publicEremove(intindex){

checkElementIndex(index); // 检查下标是否越界

return unlink(node(index));

}

/*** Unlinks non-null node x.*/

Eunlink(Node x){

// assert x != null;

final E element = x.item;

final Node next = x.next;

final Node 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; //let GC work

size--;

modCount++;

return element;

}

remove(Object o)

使用equales方法

// 删除指定元素

publicbooleanremove(Object o){

if (o == null) {

for (Node x = first; x != null; x = x.next) {

if (x.item == null) {

unlink(x);

return true;

}

}

} else {

for (Node x = first; x != null; x = x.next) {

if (o.equals(x.item)) {

unlink(x);

return true;

}

}

}

return false;

}

增删元素的时候,只需改变指针,不需要像数组那样对整体数据进行移动、复制等消耗性能的操作。

遍历

遍历的时候耗时,for循环(无穷大) > ForEach > 迭代器,优先使用迭代器方式。

```Java

for(Iterator it = list.iterator();it.hasNext();){}

```

队列操作

E peek()

// 获取第一个元素

publicEpeek(){

final Node f = first;

return (f == null) ? null : f.item;

}

E peekFirst()

// 获取第一个元素,同E peek()

publicEpeekFirst(){

final Node f = first;

return (f == null) ? null : f.item;

}

E peekLast()

// 获取最后一个元素

publicEpeekLast(){

final Node l = last;

return (l == null) ? null : l.item;

}

E pop()

// 移除第一个元素并返回

publicEpop(){

return removeFirst();

}

E pollFirst()

// 移除第一个元素,同E pop()

publicEpollFirst(){

final Node f = first;

return (f == null) ? null : unlinkFirst(f);

}

E pollLast()

// 移除最后一个元素

publicEpollLast(){

final Node l = last;

return (l == null) ? null : unlinkLast(l);

}

push(E e)

// 队首添加一个元素

publicvoidpush(E e){

addFirst(e);

}

总结

基于双向循环链表实现,不存在容量不足的问题,没有扩容的方法

增删元素快,查找慢

元素排列有序,可重复,可为null

实现了栈和队列的操作方法,因此也可以作为栈、队列和双端队列来使用。

非同步,线程不安全

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值