LinkedList的原理是链表,所以定义节点,节点要有前驱后继和内容,其add、remove、get都是基于链表的遍历
package com.ykq;
/**
* 自己实现一个LinkedList
* @author RSA
*
*/
public class MyLinkedList {
//保存链的第一个和最后一个,就能遍历整条链
private Node first;
private Node last;
//list元素个数
private int size;
//list新加节点
public void add(Object obj) {
if (first == null) {
//第一个节点为空,则链为空,则创建新节点作为头尾节点
Node n = new Node(null, obj, null);
first = n;
last = n;
} else {
//直接往last后增加节点(指定last的后继,和新节点的前驱,再将新节点指定为last)
Node n = new Node(last, obj, null);
last.setNext(n);
last = n;
}
size++;
}
//在指定下标插入新节点,原理找到该节点,然后更新相关节点前驱后继关系
public void add(int i, Object obj) {
rangeCheck(i);
Node newNode = new Node(null, obj, null);
Node temp = node(i);
temp.getPrevious().setNext(newNode);
newNode.setPrevious(temp.getPrevious());
temp.setPrevious(newNode);
newNode.setNext(temp);
size++;
}
//获取list的第i个元素
private Object get(int i) {
rangeCheck(i);
//这里提供2种方式找到目标节点,1使用循环,2使用递归
Node temp = node(i);
return temp.getObj();
//return get(i, first);递归
}
/*private Object get(int i, Node n) {
if (i == 0) {
return n.getObj();
} else {
return get(--i, (Node) n.getNext());
}
}*/
//移除指定下标的元素
public void remove(int i) {
rangeCheck(i);
Node temp = node(i);
//将被移除节点的前后节点关联起来
temp.getPrevious().setNext(temp.getNext());
temp.getNext().setPrevious(temp.getPrevious());
size--;
}
//找到指定下标的节点并返回
private Node node(int i) {
Node temp = first;
if (first != null) {
for (int j = 0; j < i; j++) {
temp = temp.getNext();
}
}
return temp;
}
//范围判断
private void rangeCheck(int index) {
//size是当前已存数据的长度,比某位元素下标多1。所以在比较时减1。为什么不需要判断index<0,原因是size本就是不小于0的,所以不用比
if (index > size-1) {
try {
throw new IllegalArgumentException("下标不合法");
} catch (Exception e) {
e.printStackTrace();
}
}
}
//获取list长度
public int size() {
return size;
}
public static void main(String[] args) {
MyLinkedList list = new MyLinkedList();
//以下三行,测试普通add
list.add("0");
list.add("1");
list.add("2");
System.out.println(list.size());
System.out.println(list.get(1));
//测试移除下标为1的元素,结果list为0、2
list.remove(1);
//测试在下标1插入3,结果为0、3、2
list.add(1,"3");
}
}