jdk源码阅读二:LinkedList
来源:互联网 发布:怎么开淘宝店铺 编辑:程序博客网 时间:2024/06/05 17:30
LinkedList介绍
LinkedList是基于链表来实现的List。主要特征如下:
- 不仅实现了List接口,还实现了Deque,所以是一个双端队列。
- 允许存储null对象。
- 非线程安全,如果多线程操作它,需要外部枷锁,或者Collections.synchronizedList。
- 返回的iterator是fail-fast,如果iterator创建后,修改了list结构则会抛出异常ConcurrentModificationException, 注意这里异常表明是一个bug,需要避免,而不能处理业务逻辑。
size 变量
size 表示当前list中存储了元素的个数,初始化为0。add一个元素加一,删除一个元素减一。
它和ArrayList定义不一样,加了transient 关键字,表明序列化时候忽略该字段。
transient int size = 0;
容量增长策略
因为是基于链表存储元素,所以容量受限于堆内存。没有扩容一说。所以不存在ensureCapacity*的方法。
接下来我们主要看看LinkedList的List和Deque功能实现。
底层存储策略
关于存储的成员变量主要如下:
transient Node<E> first;transient Node<E> last;
存储着链表的第一个和最后一个元素。
它有两个构造函数:
public LinkedList() {}public LinkedList(Collection<? extends E> c) { this(); addAll(c);}
调用默认的构造函数:first,last都是null,size =0。
调用第二个构造函数,添加了一个集合到list。
Node类
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; }}
Node类代码很简单:
- item存储具体对象。
- next表示该节点对应的下一个节点。
- prev表示该节点对应的上一个节点。
常用curd操作
插入元素
有六个add*相关方法,
add(E e)
内部调用了linkLast(e)。
void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; //判断list是否第一次插入元素 if (l == null) first = newNode; else l.next = newNode; size++; modCount++;}
每次末尾插入一个新元素,并别该元素的prev元素也添加进去。这里要说明第一次插入元素之前 list的fist和last都为null。
add(E e)
public void add(int index, E element) { //检查index是否合法,index在[0,size]之内,否则抛出异常 checkPositionIndex(index); //在末尾插入元素 if (index == size) linkLast(element); else linkBefore(element, node(index));}
linkBefore方法传一个node(index)方法。该方法就是找到index位置的Node节点。如果 index
addFirst
因为是双端队列,除了前面提到的队尾插入还有队头插入元素方法,内部调用的linkFirst方法,其实与linkLast类似。
unlink*方法分析
除了前面介绍的link*方法,还有三个unlink* 方法,作用是干嘛呢?link*是插入元素到列表,unlink其实是从链表删除一个节点意思。
- unlinkFirst:删除队头的节点。
- unlinkLast:删除队尾的节点。
- unlink :删除中间的节点
队列删除
队列有好几个remove方法 内部都是调用了unlink方法。
get
getFirst 和getLast都很快。
get(index) 内部调用的node(index)方法定位的,前面已经提到过。
indexof,contains方法分析
contains调用了indexOf,
indexof是从头开始查找,lastIndexOf从尾部开始查找,我们看下indexOf方法:
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;}
方法也是循环比较节点的内容和当前是否相等。
Deque 方法分析
Deque一般我们用的比较少。
Deque是一个线性集合,允许你在头部和尾部插入和取出数据。
LinkedList实现了Deque接口,并且他是一个非阻塞的Deque。
下面我们分析下Deque的方法实现。
add几个方法已经见过,get也见过,我们主要分析Deque几个不怎么熟悉的方法。
offer*
offer也是增加元素的意思,类似于add
offer和offerLast表示在尾部加入元素。,内部也是调用了add*方法。
offerFirst表示头部加入。下面是offerFirst代码:
public boolean offerFirst(E e) { addFirst(e); return true;}
peek*
peek是查看的意思,这里也是查看队尾或者头的元素。
peek和peekFirst 代码完全一样。
peekLast查看队尾元素。
poll*
poll类似于peek,但是他会把对应额节点删除。
pop*
pop*和poll*差不多,只是pop空节点 会抛出异常。
push
加入元素 直接调用了addFirst。
removeFirstOccurrence等
removeFirstOccurrence内部直接调用了remove。
remove从头循环删除对应的一个元素。
removeLast当然是从队尾循环删除对应的一个元素。
- jdk源码阅读二:LinkedList
- JDK源码阅读之LinkedList
- jdk源码阅读--(LinkedList)
- JDK源码阅读——ArrayList\LinkedList
- JDK源码阅读——LinkedList
- 【JDK源码阅读4-util】Collection-List---LinkedList
- JDK源码-LinkedList源码
- 【JDk源码解析之二】LinkedList源码解析
- LinkedList源码阅读
- java8 LinkedList源码阅读
- java8 LinkedList源码阅读
- LinkedList源码阅读
- LinkedList源码阅读笔记
- Java源码阅读-LinkedList
- LinkedList源码阅读笔记
- JDK源码阅读之二-----String
- JDK 1.8 HashMap 源码阅读二
- JDK1.8源码阅读系列之二:LinkedList
- 用一条语句判断一个整数是不是2的整数次方
- CCF201312--模拟练习试题参考答案(Java)
- 多线程基础(一)
- ubuntu 安装nsf(Network File System)与配置服务
- 微信小程序 仿美团分类菜单 swiper分类菜单
- jdk源码阅读二:LinkedList
- 自己搭建ngrok服务器实现树莓派内网穿透
- copyWithin的call调用实例——关于this
- 复式记账:借贷记账法
- 开发一个 app 有多难?
- ffmpeg官网例子
- LINUX自启动命令
- 编译PHP时的configure参数说明
- 将1-9数值不重复填充到9个盒子中