上一篇我们讲解了Collection接口之List子接口中的ArrayList、Vector以及Stack的实现类,由于比较简单,不在赘述,下来我们讲解List接口之LinkedList实现类
(1)LinkedList类本质上是一个双向链表,也是单向队列,双向队列,栈的实现类;
(2)LinkedList类实现了单向队列,双向队列的接口,自身也提供了栈操作的方法,链表操作的方法;
(3)LinkedList类是线程不安全的,在多线程中要保证线程安全,可使用:
List list = Collections.synchronizedList(new LinkedList());
(4)无论是链表还是队列,都特别擅长操作头和尾结点;在LinkedList中大多数方法都是
xxFirst()或者xxLast()方法的。
注意:ArrayList、LinkedList、Vector类三者都实现了List接口,共同的特点:记录元素添加顺序而且可以重复出现!
接下来我们就手动的实现一个双向链表:
(1)链表中节点的定义:
//链表中的每个结点
class Node{
Node prev; //上一节点对象
Node next; //下一节点对象
Object ele; //当前节点中储存的数据
public Node(Object ele){
this.ele = ele;
}
}
(2)链表的头插,尾插,删除(删头、删尾、删中间),获取指定key元素的值:
//手动实现 双向链表
public class MyLinkedList {
private Node first;//链表的第一个节点
private Node last;//链表的最后一个节点
private int size = 0;//节点的数量
//根据元素key,获取节点值
public Node findByKey(Object ele){
//找到被删除的节点
Node current = this.first;
for (int i = 0; i < size; i++) {
//当前节点值等于参数值
if(current.ele.equals(ele)){
break;
}
if(current.next == null){
return null;
}
current = current.next;
}
return current;
}
//向链表的头插入节点
public void addFirst(Object ele) {
Node node = new Node(ele); //新创建一个新节点
if(size == 0){
this.first = node;//当前链表无节点,头和尾都指向当前结点
this.last = node;
}else{
//新增节点的下一节点指向第一个节点
node.next = this.first;
//第一个节点的前驱指向新增节点
this.first.prev = node;
//头节点前移
this.first = node;
}
size++;
}
//向链表的尾部添加节点
public void addLast(Object ele) {
Node node = new Node(ele);//需要保存一个节点对象
if(size == 0){
this.first = node; //当前链表无节点,头和尾都指向当前结点
this.last = node;
}else{
//最后一个节点的后驱指向新增节点
this.last.next = node;
//新增节点的前驱指向最后一个节点
node.prev = this.last;
//最后节点后移
this.last = node;
}
//节点数增加一
size++;
}
//删除指定的元素值
public void remove(Object ele){
//找到被删除的节点
Node current = this.first;
for (int i = 0; i < size; i++) {
if(!current.ele.equals(ele)){
if(current.next == null){
return;
}
current = current.next;
}
}
//删除节点
if(current == this.first){ //删头
this.first = current.next;
this.first.prev = null;
}else if(current == this.last){//删尾
this.last = current.prev;
this.last.next = null;
}else{//删中间
current.prev.next = current.next;
current.next.prev = current.prev;
}
size--; //长度减一
}
//打印所有节点的元素值
@Override
public String toString() {
if(size == 0){
return "[]";
}
StringBuilder sb = new StringBuilder(size * 2 + 1);
Node current = this.first;//第一个节点
sb.append("[");
for (int i = 0; i < size; i++) {
sb.append(current.ele);
if(i != size - 1){
sb.append(",");
}else{
sb.append("]");
}
current = current.next; //获取下一个节点
}
return sb.toString();
}
//链表中的每个结点
class Node{
Node prev; //上一节点对象
Node next; //下一节点对象
Object ele; //当前节点中储存的数据
public Node(Object ele){
this.ele = ele;
}
}
}
(3)测试代码:
public class MyLinkedListDemo {
public static void main(String[] args) {
MyLinkedList list = new MyLinkedList();
list.addLast("D");
list.addLast("E");
list.addLast("F");
list.addFirst("C");
list.addFirst("B");
list.addFirst("A");
list.remove("C");
System.out.println(list.toString());
Node keyNode = list.findByKey("D");
System.out.println(keyNode.ele);
}
}