java设计模式之—迭代器 Iterator (案例:分别模仿ArrayList 、LinkList 实现Collection接口 和 Iterator迭代方法)

本文通过模拟ArrayList和LinkedList实现Collection接口,详细介绍了如何设计和实现Iterator迭代器,包括add()、size()方法,并探讨了设计模式在实际开发中的应用。文章特别强调了LinkedListIterator的实现难度,鼓励读者深入理解和消化。
摘要由CSDN通过智能技术生成

题目:分别模拟ArrayList 、LinkList 的 add() 、size() 、以及Iterator 迭代方法。并尝试模拟generic 泛型。

要求:不允许使用JDK自带的这些方法。

目的:深入了解设计模式,了解ArrayList、LinkList都共同实现了Collection接口,以及他们拥有共同的迭代方法,这种设计思想。

设计思路:

1、先创建一个Collection接口,接口中包含三个方法:add()、size()、Iterator().

2、创建Iterator类,里面分别构造hasNext()、next()方法。

     注:这个类,会涉及到一个Node节点类。

3、分别创建ArrayList类、LinkList类,都实现Collection接口。

4、创建任意对象类,猫猫狗狗,都可以,用来协助测试。

5、尝试实现generic泛型,作为了解就可以。

具体实现:

一、准备工作,创建基础类。

//创建接口类,提供3个常用基础方法
public interface Collection  {
	void add(Object obj);
	int size();
	Iterator iterator();
}

//提供迭代器两个基础方法
public interface Iterator {
	 Object next();
	 Boolean hasNext();
}
//2、创建对象类,简单点儿就好
public class Cat {
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Cat(String name) {
		super();
		this.name = name;
	}

	@Override
	public String toString() {
		return "Cat [name=" + name + "]";
	}
	
}
//3、创建Node节点类(这个对于初学者,相对比较难以想象)
public class Node {
	
	public Object objectSelf;//节点本身
	public Node nextNode;//节点链接的下一个节点
	
	public Object getObjectSelf() {
		return objectSelf;
	}
	public void setObjectSelf(Object objectSelf) {
		this.objectSelf = objectSelf;
	}
	public Node getNextNode() {
		return nextNode;
	}
	public void setNextNode(Node nextNode) {
		this.nextNode = nextNode;
	}
	public Node(Object objectSelf, Node nextNode) {
		super();
		this.objectSelf = objectSelf;
		this.nextNode = nextNode;
	}
	
}

二、具体代码实现。

1、创建ArrayList并实现Collection接口。    知识点:对数组的自动扩充(这个不是很常用)。

注:下面的Iterator的实现,相对比较容易理解。

public class ArrayList implements Collection {
	private  int index=0;
	private  Object[] objects=new Object[10];
	
	@Override
	public void add(Object obj) {
		if(index==objects.length-1) {
			Object[] newObjects=new Object[objects.length*2];//如果数组的长度满了,自动扩充
			System.arraycopy(objects, 0, newObjects, 0, objects.length);
			objects=newObjects;
		}
		objects[index]=obj;
		index++;
	}

	@Override
	public int size() {
		return index;
	}

	public Object[] getObjects() {
		return objects;
	}

	public void setObjects(Object[] objects) {
		this.objects = objects;
	}
 
	@Override
	public Iterator iterator() {
		return new ArrayListIterator();//下面的类可以写成内部类
	}

	private class ArrayListIterator implements Iterator{
		private int currentIndex=0;//记录当前迭代到哪个索引了
		@Override
		public Boolean hasNext() {
			if(currentIndex<index) return true;
			return false;
		}
		@Override
		public Object next() {
			Object object=objects[currentIndex];
			currentIndex ++;
			return object;
		}
	}
}

2、创建LinkList并实现Collection接口。    难点:对LinkList本身的了解,以及设计思路。

注:LinkListIterator 具体实现,也是难点。要做重点的消化吸收。

public class LinkedList implements Collection {
	Node headNode=null;//第一个节点
	Node tailNode=null;//最后(尾巴)一个节点
	int size=0;//已经存了几个对象
	
	@Override
	public void add(Object obj) {
		Node newNode=new Node(obj,null);
		
		// 判断这个链表是否有元素,没有的话新元素既是头也是尾
		if(headNode==null) {
			//当且仅当,只有一个节点时,这个节点,即是头,又是屁股。
			headNode=newNode;
			tailNode=newNode;
		}else {
			// 如果链表不为空,那么就把这个链表的最后一个节点指向这个新节点,最后把这个新节点设置为表尾
			tailNode.setNextNode(newNode);
			tailNode=newNode;
		}
		size++;
	}
	@Override
	public int size() {
		return size;
	}
	 
	@Override
	public Iterator iterator() {
		return new LinkListIterator();
	}
	
	private class LinkListIterator implements Iterator{
		
		Node currentNode = headNode;// 定义一个变量指向当前迭代的节点,初始值是表头

		@Override
		public Boolean hasNext() {
			return currentNode!= null;// 判断当前节点是否为空,非空的话就说明链表还有未迭代的节点,返回true
		}
		@Override
		public Object next() {
			Object obj = currentNode.getObjectSelf();// 获得当前节点的内容
			currentNode = currentNode.getNextNode();// 使指针指向下一个节点(下一个节点有可能是空值)
			return obj;
		}
	}
	 
}

3-1 创建ArraList的测试类,对代码进行测试。


public class ArrayTest {
	//常规遍历方法
	public void commWay(ArrayList list) {
		Object[] objects=list.getObjects();
		//特别注意:
		//下面for循环()内的list.size()不能替换为objects.length(否则会报空指针异常)。
		//原因:数组的长度是固定的,在这里是20。list.size()获取的是里面存有几个对象。list.size()<=objects.length
	    for (int i = 0; i < list.size(); i++) {
			Cat cat=(Cat)objects[i];
			System.out.println(cat.getName());
		}
		
	}
	public static void main(String[] args) {
		ArrayList  list=new ArrayList();
		for(int i=0;i<15;i++) {
			list.add(new Cat("咪咪"+i));
		}
		System.out.println(list.size());
			
		//new ArrayTest().commWay(list);
		
		Iterator it=list.iterator();
		
		while (it.hasNext()) {
			Cat cat=(Cat)it.next();
			System.out.println(cat.getName());
		}
	}
}

运行结果:

15
咪咪0
咪咪1
咪咪2
咪咪3
咪咪4
咪咪5
咪咪6
咪咪7
咪咪8
咪咪9
咪咪10
咪咪11
咪咪12
咪咪13
咪咪14

3-2 创建LinkList的测试类,对代码进行测试。


public class LinkTest {
	
	public static void main(String[] args) {
		Collection col=new LinkedList();
		for(int i=0;i<15;i++) {
			col.add(new Cat("咪咪"+i));
		}
		
		System.out.println(col.size());
		
		Iterator it=col.iterator();
		while (it.hasNext()) {
			Cat cat=(Cat)it.next();
			System.out.println(cat.getName());
		}
	}
}

测试结果:

15
咪咪0
咪咪1
咪咪2
咪咪3
咪咪4
咪咪5
咪咪6
咪咪7
咪咪8
咪咪9
咪咪10
咪咪11
咪咪12
咪咪13
咪咪14

4、模拟泛型。这个经常用,不是很难,不做累述。


//模拟泛型
public class GenericList<T>  {
	private  int index=0;
	private  Object[] objects=new Object[10];
	
	public void add(T obj) {
		if(index==objects.length-1) {
			Object[] newObjects=new Object[objects.length*2];
			System.arraycopy(objects, 0, newObjects, 0, objects.length);
			objects=newObjects;
		}
		objects[index]=obj;
		index++;
	}

	public int size() {
		return index;
	}

	public static void main(String[] args) {
		GenericList<String> genericList=new GenericList<>();
		genericList.add("aa");
	}
}

5、总结:

所谓的这些模式,比如:iterator,在开发中经常用到,只是我们是无感的,在开发过程中,一直以为23中设计模式很神秘,一探究竟。结果是,部分模式,在无形中我们已经在用了。

无招胜有招,但是:如果时间允许,这些设计模式,还是很有必要抽时间研磨一番,不要刻意去使用或生搬硬套,用到刚刚好就好,他们的界限有时候没有那么清晰。

上面代码写的比较粗鄙,一来自己可以回味,二来,希望能起到抛砖引玉的作用。(重点在LinkList,这个开发中不常用,可以重点记忆一下)

希望能和大家共勉!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值