首先 LinkedList 的底层实现其实是一个双向链表,这个是最主要的,在后面的add、get、remove 都会用到这个原理。
下面是我的手写源码,代码中有注释,我运行了下,应该没有问题,如果有问题,请指出,我会改进,谢谢!
/**
* @description: 实现 LinkedList 基本的增删查询
* @author: Rule
* @date: 2018-09-09 18:14
**/
public class TestLinkedList<E> {
// 双向链表使用的实际长度
transient int size = 0;
// 链表的头节点
transient Node first;
// 链表的尾节点
transient Node last;
// 用于遍历时,记录遍历的次数
private int nextIndex;
//节点的信息 双向链表包括上一个节点和下一个节点的信息,而且还包括该节点的值
private static class Node<E>{
private E item;
private Node<E> prev;
private Node<E> next;
}
//无参构造函数
public TestLinkedList(){
}
//添加操作 (不含下标)
public void add(E e){
//new node 来保存添加信息
Node<E> node = new Node<>();
node.item = e;
//如果头节点为空,则说明该链表现在是空链表
if (first == null){
first = node;
last = first;
}else {
//头节点不会空
last.next = node;
node.prev = last;
last = node;
}
//实际长度++
size++;
}
//添加操作 (含下标)
public void add(int index, E e){
//checkIndex 中没有考虑在size处添加(即末尾处)
Node<E> newNode = new Node<>();
newNode.item = e;
//首先要查询该下标是否有值
Node<E> oldNode = getNode(index);
if (oldNode == null) {
//olcNode == null 说明该链表要么是空链表,要么是在末尾添加数据
if(index == 0) {
//在首部添加数据
first = newNode;
last = first;
}else {
//在末尾添加数据
last.next = newNode;
newNode.prev = last;
last = newNode;
}
}else {
if (index == 0) {
//在链表的首部插入
first.prev = newNode;
newNode.next = first;
first = newNode;
} else {
//检查 index 是否合法
checkIndex(index);
//得到当前下标的 node
// Node<E> oldNode = getNode(index);
oldNode.prev.next = newNode;
newNode.prev = oldNode.prev;
oldNode.prev = newNode;
newNode.next = oldNode;
}
}
size++;
}
//根据下标元素删除
public void remove(int index){
//首先进行检查下标是否合法
checkIndex(index);
//查找到需要删除的节点信息
Node<E> oldNode = getNode(index);
//System.out.println("index = " + index);
//System.out.println("size = " + size);
if (index == 0){
first = oldNode.next;
first.prev = null;
}else if (index == size - 1){
last = oldNode.prev;
last.next = null;
}else {
oldNode.prev.next = oldNode.next;
oldNode.next.prev = oldNode.prev;
}
size--;
}
//得到下标节点的值
public E get(int index){
return (E) getNode(index).item;
}
//查询得到节点 (从 first 节点往后逐个遍历)
public Node getNode(int index){
if (index != 0){
//首先检查 index 是否合法
checkIndex(index);
}
Node node = first;
nextIndex = 0;
while(hasNext()){
if (nextIndex == index){
return node;
}
nextIndex++;
node = node.next;
}
return null;
}
private void checkIndex(int index) {
if (index < 0 || index >= size){
throw new IndexOutOfBoundsException("index 越界啦!!");
}
}
//遍历元素是否结束
private boolean hasNext() {
return nextIndex < size;
}
}