看一下linkedList的源码,也相当于复习了一下链表的增删改查
常量定义
-
int size = 0; 链表中元素的个数
-
Node first; 指向头结点
-
Node last; 指向尾结点
Node类
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {...}
}
由node类的定义可以看出linkedList底层是一个双向链表
添加元素
头部添加
- 使用** f **存储当前链表的头节点(执行添加操作前的头节点)
- 新创建一个节点Node作为头结点,prev指向 null ,next指向之前的头节点f。
- 更新first头节点(由于在头部添加了新的节点,first为新创建的节点)
- 如果f为null(由于该方法是添加元素在头部,f为null,创建node前链表是空的),说明是第一次执行添加。此时头结点和尾结点是相同的。把新创建的节点赋值last节点
- first节点的prev始终为null。由于新创建一个node追加在头部,需要f(执行添加操作前的头节点)的prev指向新创建的节点
尾部追加
- 使用 l存储当前链表的尾节点(执行添加操作前的尾节点)
- 新创建一个节点Node作为尾结点,prev指向 l ,next置空。
- 更新last尾节点(由于在尾部添加了新的节点,last应为新创建的节点)
- 如果l为null(由于该方法是追加元素在尾部,l为null,说明创建node前链表是空的),说明是第一次执行添加。此时头结点和尾结点是相同的。此时把新创建的节点赋值first节点
- last节点的next始终为null。由于新创建一个node追加在尾部,需要l(执行添加操作前的最后一个节点)的next指向新创建的节点
在头部添加节点和尾部添加节点逻辑几乎一致
移除元素
E unlink(Node<E> x) {
final E element = x.item;
final Node<E> next = x.next;
final Node<E> 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;
size--;
modCount++;
return element;
}
- 记录被移除元素的前一个节点prev和后一个节点next
- 判断prev。为null,即删除的元素为头结点。只需更新first节点指向当前节点的next。不为null,prev的下一个节点指向next。切断删除节点与链表的关联
- 判断next。为null,即删除的元素为尾结点。只需更新last节点指向prev。不为null,next的上一个节点指向prev。切断节点元素与链表的关联
-
头结点 first = 当前节点的next
-
尾结点 last = 当前节点的prev
-
中间节点 prev.next = next, next.prev = prev
查找节点
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;
}
遍历链表,查找对应得到元素,如果找到了,返回下标,没有找到,返回-1;
我发现查找null和不为null的代码就一行不一样。为什么不合并呢?
if (x.item == null) // if (o.equals(x.item))
- == 替换 equals 当查找的元素为null时,不论o还是x.item调用equals都会抛出NPE
- equals 替换 == 这就必须要明白equals和==的区别。 这个方法找的是Object对应的位置。我们查找的是值,而不是查找对地址的引用。
equals与==区别
-
equals()是对字符串的内容进行比较
-
==是指对内存地址进行比较
验证
根据LinkedList的源码写了一个Node类,简单的add,indexof方法。使用‘==’判断是否相等
public class Node <E> { private Node<E> first; private Node<E> last; private E data; private Node<E> next; public Node() {} public Node(E data, Node<E> next) { this.data = data; this.next = next; } void addLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(e, null); last = newNode; if (l == null) { first = newNode; } else { l.next = newNode; } } public int indexOf(Object o) { int index = 0; for (Node<E> x = first; x != null; x = x.next) { if (o == x.data) { return index; } index++; } return -1; }}
-
首先测试Integer,输入12,预计返回0,结果返回0,正确
Node node = new Node<>();node.addLast(12);node.addLast(12);System.out.println(node.indexOf(12));
-
输入12345,预计返回0,结果-1,错误
Node<Integer> node = new Node<>();node.addLast(12345);node.addLast(12345);System.out.println(node.indexOf(12345));
int常量池中初始化-128~127的范围,所以当为Integer i=127时,在自动装箱过程中是取自常量池中的数值,而当Integer i=128时,128不在常量池范围内,所以在自动装箱过程中需new 128,所以地址不一样。地址不一样,数值一样,‘’==‘’是false
结论
(方法结论)不能合并。
()明明知道结果是不能替换,但还是花费时间做了验证。归根结底还是对知识掌握不牢固,对自己不自信,害怕出错。