源码之LinkedList
Posted 保护眼睛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了源码之LinkedList相关的知识,希望对你有一定的参考价值。
源码之LinkedList
Linked List:首先LinkedList底层是一个双向的链表、链表的结点是带有前驱节点和后继节点、以及值item 的结点。
常见的方法:
getFirst 和 getLast方法将链表的第一个结点或者尾结点保存、如果首或尾结点为空的话、抛出异常、否则返回结点的值。
RemoveFirst 和 remove Last方法将first 或者 last结点的值赋给l,判断l是否为空、为空就抛出异常、否则调用unlinkFirst和unlinkLast方法来删除头或者尾结点。
头插、尾插
AddFirst 和addLast 方法分别调用了linkFirst:如果链表的first节点是空的话、插入的节点也是链表的last,否则将传入的值插入到链表的first前size++、linkeLast方法也是类似的。
代码的逻辑也是很清楚的。
conttains方法调用的indexOf方法
indexOf方法如果为null的话、返回对应的index下标、不为null的话使用equals方法来判断要找的值是否存在与链表中。当x == null 的时候、还没有找到的话、返回-1.
add方法和size方法
add方法调用的时linkLast方法、也就是每次使用add方法来增加 元素的时候、都是将元素插入到链表的尾部的。每次进行插入和删除的操作的时候、链表对应的size就++或者–。
Remove方法
代码的逻辑也是非常的清楚的。根据传入的结点的item来删除对应的结点、如果链表里面存的是引用类型的值的话、那么也有可能存的结点的值本来就是null、所以要使用 == 来判断是不是null、如果使用的equals 的方法来判断null的话、来看
就会报Null Pointer Exception的异常。所以要加非空的判断。
来看addAll方法:将指定的集合添加到链表中带有一个参数的addAll方法调用的带有两个参数的addAll的方法、
直接在链表的末尾将集合插入到链表中去
来看带有两个参数的addAll方法
public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index);
Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false;
Node<E> pred, succ;
if (index == size) {
succ = null;
pred = last;
} else {
succ = node(index);
pred = succ.prev;
}
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
first = newNode;
else
pred.next = newNode;
pred = newNode;
}
if (succ == null) {
last = pred;
} else {
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
第一个参数是要插入到链表中的位置、第二个参数是要插入的集合
首先对index的位置进行合法的检查、然后将这个集合转变为object类型的数组、得到数组的长度、如果传入的集合的长度是0 的话、那么直接return false、定义两个结点pred、succ、如果要插入的位置如果是链表的长度的话将succ置为nul将pred置为链表的last。不然的话、调用node(index)方法将succ置为链表中对应的index位置的结点、将pred置为succ的前驱节点。然后就是遍历数组、每次创建出数组中的对应元素的结点、对pred做非空的检验、因为如果链表的长度为0 的话或者succ结点的位置就是链表的first结点的话、那么直接就让新的元素生成的结点置为新的链表的first结点、否则的话、就以此插入到pred的next的位置、每次插入完成之后、将pred指向newNode、也就是链表的最后的位置。将数组的中的元素都添加完成之后、判断succ是否为null、为null也就是刚开始的时候、链表的长度为0或者插入的集合的位置在链表的末尾插入的、pred在插入完成之后就会移动到下一个节点的前驱、也就是pred如果初始的链表的长度为0的话、那么pred就在插入后的链表的最后一个位置上、所以链表的last就是pred、否则pred就一直是succ的前驱结点。插入完成之后链表的长度就是之前链表的长度加上集合转化的数组的长度。
node(index)方法:返回指定索引处的非空的结点。也是很直观的、先对index做出判断、是否小于链表的长度的1/2、小于的发就从链表的first的位置开始找、否则的话、就从后面找。
clear方法:删除链表的所有的节点、方法的逻辑也是很清楚的、在删除结点的item、next、prev的之前、先保存结点的next、之后赋值。最后将first、last也置为null。
get方法和set方法的逻辑也是非常的清楚的:
get得到链表指定index结点的值,set方法将链表指定index位置的元素的值更改。
add方法在链表指定index位置插入新节点。如果index的位置就是链表的size的位置的话、那么直接插入到链表的末尾就可以了。否则的话调用linkBefore 方法来将element元素对应的结点插入到index对应的位置上。
remove方法用来删除指定的位置index的结点、首先对index的位置进行判断、然后调用unlink方法来对这个位置的结点进行删除操作 。
来看unlink方法:
首先得到要删除的节点的item、next、prev让第一个判断是看要删除的节点是不是链表的first头节点、如果要删除的节点就是链表的第一个节点的话、那么直接让链表的first置为要删除的节点的next即可、如果要删除的节点不是链表的第一个节点的话、那么让要删除的节点的前驱节点指向要删除节点的next即可、然后将要删除节点的前驱置为null、方便GC来回收。要删除的节点的next也是一样的。最后将要删除的节点的item置为null、size–。返回删除节点的item、即返回要删除的点的值域。
当然LinkedList的方法不止这些,LinkedList也是用来实现队列的。还有队列所对应的方法。
以上是关于源码之LinkedList的主要内容,如果未能解决你的问题,请参考以下文章