java迭代子模式详解
迭代子(Iterator)模式的结构:
迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。
迭代子可分为外禀迭代子和内禀迭代子。
外禀迭代子:适合于白箱聚集(白箱聚集就是向外界提供访问自己内部元素接口的聚集),由于迭代的逻辑是由聚集对象本身提供的,所以这样的外禀迭代子角色往往仅仅保持迭代的游标位置。所以具体迭代子角色是一个外部类,它的构造函数接受一个具体聚集对象,从而可以调用这个聚集对象的迭代逻辑。
内禀迭代子:适用于黑箱聚集(黑箱聚集不向外部提供遍历自己元素对象的接口),由于黑箱聚集的元素对象只可以被聚集内部成员访问,所以内禀迭代子只能是聚集内部的成员子类。
简单示范:
package test.edu.inter; public interface IteratorObj { /** * 移动到第一个元素 */ public void first(); /** * 移动到下一个元素 */ public boolean hasNextItem(); /** * 返还当前元素 */ public Object currentItem(); } package test.edu.inter; public interface DataSet { public IteratorObj getIterator(); } package test.edu.inter; public class Iterator1 implements IteratorObj { private Dataobj set; private int size; private int index=0; public Iterator1(Dataobj set){ this.set = set; this.size = set.getSize(); } @Override public void first() { // TODO Auto-generated method stub this.index = 0; } @Override public boolean hasNextItem() { if(index<size){ return true; } return false; } @Override public Object currentItem() { Object ob = set.getItem(index); if(index<size){ index++; } return ob; } } package test.edu.inter; public class Dataobj implements DataSet { private Object[] objArray = null; /** * 传入聚合对象 */ public Dataobj(Object[] objArray){ this.objArray = objArray; } @Override public IteratorObj getIterator() { return new Iterator1(this); } public Object getItem(int index){ return objArray[index]; } public int getSize(){ return objArray.length; } } package test.edu.inter; public class Client { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub String[] str={"12312","dasda","dasd","12d","asd"}; Dataobj ao = new Dataobj(str); IteratorObj io = ao.getIterator(); while(io.hasNextItem()){ System.out.println(io.currentItem()); } } }
运行结果:
12312 dasda dasd 12d asd
内容扩充:在java聚集中的应用
在java.util.Collection接口提供iterator()工厂方法返回一个Iterator类型对象,Collection接口的子类型AbstractList类的内部成员类Itr实现Iterator接口。所以Itr是内禀迭代子类,但是AbstractList也提供了自己的遍历方法,所以它不是黑箱聚集,而是白箱聚集。其代码如下:
import java.util.Iterator; public interface Itr extends Iterator{ //再次调用next()方法时所用的指标 int cursor = 0; //最近一次调用时所用的指标 int lastRet = -1; int expectedModCount = modCount; public boolean hasNext(){ return cursor!=size(); } public Object next(){ try{ Object next = get(cursor); checkForComodification(); lastRet = cursor++; return next; }catch(IndexOutOfBoundsException e){ checkForComodification(); throw new NoSuchElementException(); } } //删除最后遍历过的元素,remove()方法只能删除最后遍历的元素 public void remove(){ if(lastRet ==-1) throw new IllegalStateException(); checkForComodification(); try{ AbstractList.this.remove(lastRet); if(lastRet<cursor) cursor--; lastRet = -1; expectedModCount = modCount; }catch(IndexOutOfBoundsException e){ throw new ConcurrentModificationException(); } } public void checkForComodification(){ if(modCount!=expectedModCount) throw new ConcurrentModificationException(); } }
其中的modCount、get(cursor)等变量和方法均是AbstractList类所拥有,Itr可以直接使用。方法checkForComodification()会检查聚集的内容是否刚刚被外界直接修改过(不是通过迭代子提供的remove()方法修改的)。如果在迭代子开始后,聚集的内容被外界绕过迭代子对象而直接修改过年话,这个方法立即抛出异常。
另外:AbstractList类也提供了listIterator()方法,返回一个实现了Listiterator接口的类ListItr实例。ListIterator接口实现了正向迭代和逆向迭代,同时还提供了在迭代过程当中安全修改列的内容的方法。
Enumeration与Iterator的区别:(1)Enumeration没有remove方法(2)Enumeration是在Vector中的element()方法中作用一个无名类实现的,它不支付Fail Fast,也就是说在迭代过程中,聚集对象被外界意外直接修改,则这个迭代过程还会立即捕获任何异常。
以上就是本文的全部内容,希望对大家的学习有所帮助。