线性表中迭代器的内部实现(Iterator、ListIterator)

      迭代器(Iterators)是对数据集进行遍历的对象,在遍历过程中,可以查看、修改、添加以及删除元素。Java类库中有两个有关迭代器的接口:Iterator和ListIterator,它们为迭代器指定了方法,可以将迭代器方法添加到ADT线性表的操作中,也可以将迭代器定义为一个与ADT线性表相互作用的单独的类。Java中还提供了一个Iterable接口,该接口的Iterator方法返回一个标准的Iterator实现。

     独立的迭代器与内部的迭代器

     独立类迭代器必须通过ADT的公用方法来访问ADT的数据,如果某些ADT,如堆,没有提供足够的数据访问方法,使得不能实现这种迭代器。另外,独立类迭代器比其他类型的迭代器的运行时间要长。但是,独立类的迭代器的实现往往比较简单。内部类迭代器可以直接访问ADT的数据,因此它往往比单个类的迭代器运行速度快。其实现单价也更大。迭代器的方法为什么要在自己的类中?因为如果迭代器的方法在ADT中,某个时候只能有一个遍历,而且,需要使用一些不属于接口Iterator的操作来初始化遍历。

    Iterator接口

    Java类库在java.util包中提供了该接口。Iterator接口只描述了3个方法:hasNext、next和remove。这些方法从第一个数据元素开始遍历数据集。

    hasNext():测定迭代器是否完成遍历并越过数据集中的最后一个元素,若是,则返回false,否则返回true.

    next():提取集合集中当前(下一个)元素并迭代前进一个位置

    remove():从数据集中删除next()返回的最后一个元素,此后调用next()的行为将与删除前一样

   下面是iterator在以数组方式实现的线性表中的内部实现,在以链表实现的线性表类似。就是用nextNode=nextNode.next代替nextIndex++,判断hasNext(),就是判断nextNode是否为空。

    

	/**
	 * 在数组方式实现的线性表中,作为内部类实现其迭代器,java类库arrayList中已实现其迭代器Iterator
	 * @key
	 * @author S.M.Q 
	 * 2014年9月14日下午8:04:58
	 */
	private class IteratorForArrayList implements Iterator<T>{
		private int nextIndex;
		private boolean isCalledNext;
		IteratorForArrayList()
		{
			nextIndex=0;
			isCalledNext=false;
		}
		/**
		 * 判断是否到该线性表的最后一个元素,只要判断下一个元素的索引是否小于该线性表的长度
		 */
		public boolean hasNext()
		{
			return nextIndex<length;
		}
		/**
		 * 返回下一个元素,并将索引往前进一步
		 * 为防止数组越界,判断一下当前索引是否小于线性表的长度,否则抛出异常
		 */
		public T next()
		{
			if(nextIndex<length)
			{
				isCalledNext=true;
				return entry[nextIndex++];
			}
			else
				throw new NoSuchElementException("no illegal exception");
		}
		/**
		 * 删除的当前元素,故该方法只能在调用next之后调用,此处用isCalledNext标识next是否调用
		 * 其他调用则派出非法异常
		 */
		public void remove()
		{
			if(isCalledNext)
			{
				  MyArrayList.this.remove(nextIndex);
				  nextIndex--;
				  isCalledNext=false;
			}else
				throw new IllegalStateException(" illegal state exception");
			
		}
	}
      ListIterator接口

      该接口是Java类库中提供的另一个迭代器接口,这种迭代器允许双向遍历线性表,并且在遍历过程中可以修改线性表。除了Iterator接口说明的3个方法hasNext、next和remove之外,ListIterator还含有诸如hasPrevious、previous、add和set方法

      hasPrevious:检查迭代是否已完成遍历并到达数据集中的第一个元素之前

      previous:提取线性表中前一个元素并将迭代向前移动一个

     add:向线性表中插入元素,插入位置在next()可能返回的元素之前,previous可能返回的元素之后,插入之后,调用previous()将返回新元素,而调用next()将与插入前的一样

     set:替换线性表中由next()或previous()刚返回的最后一个元素

     下面是以数组方式实现的线性表,ListIterator作为内部类的实现,链表方式与数组方式类似:

   

	/**
	 * 数组方式实现的线性表中,作为内部类实现其迭代,java在arrayList中已经实现listIterator
	 * @key
	 * @author S.M.Q 
	 * 2014年9月14日下午9:02:28
	 */
	private class ListIteratorForArrayList implements ListIterator{
		private int nextIndex;
		private Move lastMove;
		private boolean isMoveOrSetLegal;
		/**
		 * 该迭代器可以向前向后,所以只能用一个索引,通过增减索引实现其向前或者向后
		 * 向前或向后操作略有不同,故用一个枚举来记录其动作
		 * set或remove都是对当前元素进行操作,所以要设置一个标示,看是否能进行set或remove操作
		 */
		ListIteratorForArrayList()
		{
			nextIndex=0;
			isMoveOrSetLegal=false;
			lastMove=null;
		}
		/**
		 * 与Iterator的hasNext类似
		 */
		public boolean hasNext()
		{
			return nextIndex<length;
		}
		/**
		 * 与Iterator的next类似
		 */
		public T next()
		{
			if(hasNext())
			{
				isMoveOrSetLegal=true;
				lastMove=Move.NEXT;
				return entry[nextIndex++];
			}else
				throw new NoSuchElementException("no such element exception!");
		}
		/**
		 * 查看当前索引是否大于0,如果大于0,说明当前元素不是位于线性表的第一个
		 */
		public boolean hasPrevious()
		{
			return nextIndex>0;
		}
		/**
		 * 返回当前元素的前一个元素,并将迭代向前推进一个
		 * 记录相关特征,lastMove和nextIndex
		 */
		public T previous()
		{
			if(hasPrevious())
			{
				isMoveOrSetLegal=true;
				lastMove=Move.PREVIOUS;
				nextIndex--;
				return entry[nextIndex];
			}else
				throw new NoSuchElementException("no such element exception!");
		}
		/**
		 * 移除当前元素,remove操作需要在调用next()和previous之后。才能进行操作,故根据isMoveOrSetLegal的状态来
		 * 进行是否可以进行remove操作,我实现的MyArrayList实现的remove函数的参数,是该元素的位置,而调用过next之后,当前索引加1,
		 * 调用previous之后,当前索引需要加1,才是位置(因为nextIndex是从0开始的)
		 * 最后由于移除掉一个元素,当前的索引需要自减1,因为线性表的长度减一了
		 */
		public void remove()
		{
			if(isMoveOrSetLegal)
			{
				isMoveOrSetLegal=false;
				if(lastMove==Move.NEXT)
					MyArrayList.this.remove(nextIndex);
				else
				{  
					nextIndex++;
				    MyArrayList.this.remove(nextIndex);
				}
					nextIndex--;
			}else
				throw new IllegalStateException("illegal operation!");
		}
		/**
		 * 返回下一个索引
		 */
		public int nextIndex()
		{
			int result;
			if(hasNext())
				result=nextIndex;
			else
				result=length;
			return result;
		}
		/**
		 * 返回前一个索引
		 */
		public int previousIndex()
		{
			int result;
			if(hasPrevious())
				result=nextIndex-1;
			else
				result=-1;
			return result;
		}
         /**
          * 根据标识,看是否能操作set,否则抛出异常
          * 调用线性表内部的set方法
          */
		@Override
		public void set(Object e) {
			// TODO Auto-generated method stub
			if(isMoveOrSetLegal)
			{
				if(lastMove==Move.NEXT)
					MyArrayList.this.replace(nextIndex,(T)e);
				else
					MyArrayList.this.replace(nextIndex+1,(T)e);
			}else
				throw new IllegalStateException("illeagl operation");
		}
         /**
          * 同样也是调用线性表内部的add方法
          * 然后索引需要自增1,因为线性表的长度增1了
          */
		@Override
		public void add(Object e) {
			isMoveOrSetLegal=true;
			nextIndex++;
			MyArrayList.this.add(nextIndex,(T)e);
			
		}
	}

     

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值