自己实现了一个简单的双向链表。
public class LinkedList<T> {
//起始节点,指向第一个节点
private Node<T> start;
//结束节点,指向最后一个节点
private Node<T> tail;
//链表长度
private int length;
/**
* 添加元素(尾插)
* @param data 需要添加进链表的元素
*/
public void add(T data){
tailInsert(data);
}
/**
* 添加元素(尾插)
* @param data 需要添进链表的元素序列
*/
public void add(T... data){
tailInsert(data);
}
/**
* 获取元素
* @param index 元素下标
* @return 返回下标对应的元素
*/
public T get(int index){
//下标越界
if (length - 1 < index){
throw new RuntimeException("链表没有那么多元素");
}
int i = 0;
Node<T> res = start;
while (i++ != index){
res = res.next;
}
return res.data;
}
public int size(){
return length;
}
/**
* 头插
* @param element 需要插入的数据
*/
public void startInsert(T element){
//起始节点替换为新节点
start = new Node<>(null, element, start);
//新节点放置在起始节点之前
if (start.next != null){
start.next.previous = start;
}
//如果尾节点为空,新节点就是尾节点
if (null == tail){
tail = start;
}
length++;
}
/**
* 批量头插
* @param elements 需要头插的元素序列
*/
@SafeVarargs
public final void startInsert(T... elements){
//临时链
Node<T> tempLinkStart = null;
Node<T> tempLinkTail = null;
//元素添加到临时链
for (T element : elements){
if (null == tempLinkStart && null == tempLinkTail){
tempLinkStart = new Node<>(null, element, null);
tempLinkTail = tempLinkStart;
}else{
tempLinkStart = tempLinkStart.addPrevious(element);
}
}
//临时链添加到表起始
if (null != tempLinkTail){
tempLinkTail.next = start;
if (null != start){
start.previous = tempLinkTail;
}else{
tail = tempLinkTail;
}
start = tempLinkStart;
length += elements.length;
}
}
/**
* 尾插
* @param element 需要插入的数据
*/
public void tailInsert(T element){
//替换结束节点
tail = new Node<>(tail, element, null);
//放在结束节点之后
if (tail.previous != null){
tail.previous.next = tail;
}
//如果起始节点为空,新节点就是起始节点
if (null == start){
start = tail;
}
length++;
}
/**
* 批量尾插
* @param elements 需要尾插的元素序列
*/
@SafeVarargs
public final void tailInsert(T... elements){
//临时链
Node<T> tempLinkStart = null;
Node<T> tempLinkTail = null;
//元素尾插进入临时链
for (T element : elements){
if (null == tempLinkStart && null == tempLinkTail){
tempLinkStart = new Node<>(null, element, null);
tempLinkTail = tempLinkStart;
}else{
tempLinkTail = tempLinkTail.addNext(element);
}
}
//临时链加入链表
if (null != tempLinkStart){
tempLinkStart.previous = tail;
if (null != tail){
tail.next = tempLinkStart;
}else{
start = tempLinkStart;
}
tail = tempLinkTail;
length += elements.length;
}
}
/**
* 链表节点类
*/
static class Node<E>{
//前驱节点
Node<E> previous;
//数据
E data;
//后继节点
Node<E> next;
Node() {
}
Node(Node<E> previous, E data, Node<E> next) {
this.previous = previous;
this.data = data;
this.next = next;
}
/**
* 在本节点之后插入一个元素
* @param data 需要插入的元素E
* @return 返回新插入的节点
*/
Node<E> addNext(E data){
this.next = new Node<E>(this, data, null);
return this.next;
}
/**
* 在本节点之前插入一个元素
* @param data 需要插入的元素
* @return 返回新插入的节点
*/
Node<E> addPrevious(E data){
this.previous = new Node<E>(null, data, this);
return this.previous;
}
}
}
当测试的时候就遇上了困难。我往链表里面添加了元素以后只能通过get()方法来获取到需要的元素值。
public class TestApp {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
list.add(1,2,3,4,5);
for (int i = 0; i < list.size(); i++){
System.out.println(list.get(i));
}
}
}
而官方的LinkedList是可以通过增强for循环来完成遍历的。我也希望通过增强for循环来遍历我自己的链表集合。
我们知道增强for循环底层实际是迭代器完成的。我们就需要用到迭代器模式。
实现迭代器模式的步骤
- LinkedList类实现Iterable接口
- 写一个LinkedList的迭代器类,实现Iterator<T>接口
- 迭代器类至少需要重写hasNext()方法与next()方法;
- LinkedList重写iterator()方法。
修改后的双向链表类
import java.util.Iterator;
public class LinkedList<T> implements Iterable<T>{
//起始节点,指向第一个节点
private Node<T> start;
//结束节点,指向最后一个节点
private Node<T> tail;
//链表长度
private int length;
/**
* 添加元素(尾插)
* @param data 需要添加进链表的元素
*/
public void add(T data){
tailInsert(data);
}
/**
* 添加元素(尾插)
* @param data 需要添进链表的元素序列
*/
public void add(T... data){
tailInsert(data);
}
/**
* 获取元素
* @param index 元素下标
* @return 返回下标对应的元素
*/
public T get(int index){
//下标越界
if (length - 1 < index){
throw new RuntimeException("链表没有那么多元素");
}
int i = 0;
Node<T> res = start;
while (i++ != index){
res = res.next;
}
return res.data;
}
public int size(){
return length;
}
/**
* 头插
* @param element 需要插入的数据
*/
public void startInsert(T element){
//起始节点替换为新节点
start = new Node<>(null, element, start);
//新节点放置在起始节点之前
if (start.next != null){
start.next.previous = start;
}
//如果尾节点为空,新节点就是尾节点
if (null == tail){
tail = start;
}
length++;
}
/**
* 批量头插
* @param elements 需要头插的元素序列
*/
@SafeVarargs
public final void startInsert(T... elements){
//临时链
Node<T> tempLinkStart = null;
Node<T> tempLinkTail = null;
//元素添加到临时链
for (T element : elements){
if (null == tempLinkStart && null == tempLinkTail){
tempLinkStart = new Node<>(null, element, null);
tempLinkTail = tempLinkStart;
}else{
tempLinkStart = tempLinkStart.addPrevious(element);
}
}
//临时链添加到表起始
if (null != tempLinkTail){
tempLinkTail.next = start;
if (null != start){
start.previous = tempLinkTail;
}else{
tail = tempLinkTail;
}
start = tempLinkStart;
length += elements.length;
}
}
/**
* 尾插
* @param element 需要插入的数据
*/
public void tailInsert(T element){
//替换结束节点
tail = new Node<>(tail, element, null);
//放在结束节点之后
if (tail.previous != null){
tail.previous.next = tail;
}
//如果起始节点为空,新节点就是起始节点
if (null == start){
start = tail;
}
length++;
}
/**
* 批量尾插
* @param elements 需要尾插的元素序列
*/
@SafeVarargs
public final void tailInsert(T... elements){
//临时链
Node<T> tempLinkStart = null;
Node<T> tempLinkTail = null;
//元素尾插进入临时链
for (T element : elements){
if (null == tempLinkStart && null == tempLinkTail){
tempLinkStart = new Node<>(null, element, null);
tempLinkTail = tempLinkStart;
}else{
tempLinkTail = tempLinkTail.addNext(element);
}
}
//临时链加入链表
if (null != tempLinkStart){
tempLinkStart.previous = tail;
if (null != tail){
tail.next = tempLinkStart;
}else{
start = tempLinkStart;
}
tail = tempLinkTail;
length += elements.length;
}
}
@Override
public Iterator<T> iterator() {
return new LinkedListIterator<>();
}
/**
* 链表节点类
*/
static class Node<E>{
//前驱节点
Node<E> previous;
//数据
E data;
//后继节点
Node<E> next;
Node() {
}
Node(Node<E> previous, E data, Node<E> next) {
this.previous = previous;
this.data = data;
this.next = next;
}
/**
* 在本节点之后插入一个元素
* @param data 需要插入的元素E
* @return 返回新插入的节点
*/
Node<E> addNext(E data){
this.next = new Node<E>(this, data, null);
return this.next;
}
/**
* 在本节点之前插入一个元素
* @param data 需要插入的元素
* @return 返回新插入的节点
*/
Node<E> addPrevious(E data){
this.previous = new Node<E>(null, data, this);
return this.previous;
}
}
/**
* 迭代器
* @param <T>
*/
private class LinkedListIterator<T> implements Iterator<T>{
Node<T> iter;
public LinkedListIterator() {
iter = (Node<T>) new Node<>(null,null,start);
}
@Override
public boolean hasNext() {
iter = iter.next;
return iter != null;
}
@Override
public T next() {
return iter.data;
}
}
}
增强for循环遍历的结果