数据结构之双向链表

      本来这次博文要介绍Handler、Message、Looper之间的关系的,但是,我觉得,在讲这个之前我觉得有必要讲一下列表,因为什么呢?我这是为了,下面讲Handler、Message、Looper之间的关系时,需要用到,因为Handler里有个消息队列用到了链表。 好了,咱么开门见山,下面我们就开始来看看双向列表如何实现:

     这个代码也是比较简单的,首先不要怪我直接贴代码,因为这个用文字来描述感觉很晦涩,所以我会以代码跟图的结合方式来说:


首先我们来说说双向列表的添加方法:

/**
	 * 添加节点数据
	 * @param data
	 */
	public void add(Object data){
		//将数据封装到节点里面去
		Node node = new Node(data);
		if(head == null){//①
			//如果head为空,那么node是不是就是头节点,head、rear都指向它
			head = node;
			rear = node;
		}else{//否则,那么就代表不为空,要么往前加,要么往后加
			
			rear.next = node;
			node.prev = rear;
			rear = node;
			
		}
	}
下面用一副图来帮助理解:



那么接下来,我就来看看删除的方法:

/**
	 * 查找节点
	 * @param data
	 */
	private Node find(Object data){
		Node node = head;
		while(node != null){
			if(node.data.equals(data) && node.data.hashCode() == data.hashCode()){//找到了
				break;
			}else{//没找到,指向下一个
				node = node.next;
			}
		}
		return node;
	}
	/**
	 * 删除节点
	 * @param data
	 */
	public void remove(Object data){
		Node node = find(data);
		if(node != null){
			if(node == head && node == rear){//找到,删除
				head = null;
				rear = null;
			}else if(node == head){//头节点
				head = head.next;
				head.prev = null;
			}else if(node == rear){//尾节点
				rear = rear.prev;
				rear.next = null;
			}else{//中间节点
				head.prev.next = node.next;
				head.next.prev = node.prev;
				
			}

		}
	}

同样是一段code,我相信大家应该看的懂,加上了注释应该好理解,下面同样用一幅图来表示:


我相信有了图,应该很好理解,对吧。对大家来说理解起来应该更加清晰。当然,如果你需要实现迭代的功能,你也可以实现Iteratorable接口,这里我也为大家实现了这一个功能,不过这里我会贴出全部代码:因为这样看起来更加全面。

import java.util.Iterator;
import java.util.Spliterator;
import java.util.function.Consumer;


public class MyDoubleLink implements Iterable<Object>{
	
	
	private class Node{
		
		public Node(Object data){
			this.data = data;
		}
		
		Node next;
		Node prev;
		Object data;
	}
	private Node head;//头节点
	private Node rear;//尾节点
	/**
	 * 添加节点数据
	 * @param data
	 */
	public void add(Object data){
		//将数据封装到节点里面去
		Node node = new Node(data);
		if(head == null){//①
			//如果head为空,那么node是不是就是头节点,head、rear都指向它
			head = node;
			rear = node;
		}else{//否则,那么就代表不为空,要么往前加,要么往后加
			
			rear.next = node;
			node.prev = rear;
			rear = node;
			
		}
	}
	
	/**
	 * 查找节点
	 * @param data
	 */
	private Node find(Object data){
		Node node = head;
		while(node != null){
			if(node.data.equals(data) && node.data.hashCode() == data.hashCode()){//找到了
				break;
			}else{//没找到,指向下一个
				node = node.next;
			}
		}
		return node;
	}
	/**
	 * 删除节点
	 * @param data
	 */
	public void remove(Object data){
		Node node = find(data);
		if(node != null){
			if(node == head && node == rear){//找到,删除
				head = null;
				rear = null;
			}else if(node == head){//头节点
				head = head.next;
				head.prev = null;
			}else if(node == rear){//尾节点
				rear = rear.prev;
				rear.next = null;
			}else{//中间节点
				head.prev.next = node.next;
				head.next.prev = node.prev;
				
			}

		}
	}

	@Override
	public void forEach(Consumer<? super Object> arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Iterator<Object> iterator() {//实现增强for循环
		Iterator<Object> ite = new Iterator<Object>() {
			
			private Node temp = head;
			
			@Override
			public void forEachRemaining(Consumer<? super Object> arg0) {
				
			}

			@Override
			public boolean hasNext() {
				return temp != null;
			}

			@Override
			public Object next() {
				Object data = temp.data;
				temp = temp.next;
				return data;
			}

			@Override
			public void remove() {
				
			}
		};
		return null;
	}

	@Override
	public Spliterator<Object> spliterator() {
		return null;
	}

	
	
	

}

好了,就到这里了,我觉得这个对理解MessageQueue非常有好处。如果童鞋们不想黏贴之类的麻烦,我也会把代码打包上传到CSDN资源库,到时候大家下载即可。欢迎大家拍砖啊,我需要你们吐槽啊。看完这篇,大家就可以看看 阅读源码,让你彻底理解Handler、Message、Looper之间的关系,相信这篇对你理解他们之间的关系,是很有帮助的。

源码在这:点击打开链接


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值