线性表中迭代器的内部实现(Iterator、ListIterator)
2014-09-14 19:07
351 查看
迭代器(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类库中提供的另一个迭代器接口,这种迭代器允许双向遍历线性表,并且在遍历过程中可以修改线性表。除了Iterator接口说明的3个方法hasNext、next和remove之外,ListIterator还含有诸如hasPrevious、previous、add和set方法
hasPrevious:检查迭代是否已完成遍历并到达数据集中的第一个元素之前
previous:提取线性表中前一个元素并将迭代向前移动一个
add:向线性表中插入元素,插入位置在next()可能返回的元素之前,previous可能返回的元素之后,插入之后,调用previous()将返回新元素,而调用next()将与插入前的一样
set:替换线性表中由next()或previous()刚返回的最后一个元素
下面是以数组方式实现的线性表,ListIterator作为内部类的实现,链表方式与数组方式类似:
独立的迭代器与内部的迭代器
独立类迭代器必须通过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); } }
相关文章推荐
- arraylist的迭代器的实现研究---其中的iterator(不是listiterator)---(源码)
- Java 编程思想(第4版)学习笔记(迭代器 Iterator ListIterator 第11章练习11)
- 线性表--数组实现+模板+迭代器
- 迭代器Iterator与ListIterator的简单应用;
- C++之STL(三):迭代器类vector::iterator 和 vector::reverse_iterator 的实现、迭代器类型、常用的容器成员
- 设计模式(8) - 迭代器模式(iterator)- 实现ArrayList和linkedList的迭代器
- 在vs.net2003中实现迭代器(Iterator)
- Java 实现迭代器(Iterator)模式
- 从零开始学C++之STL(三):迭代器类vector::iterator 和 vector::reverse_iterator 的实现、迭代器类型、常用的容器成员
- 测试类图Head First 设计模式 (九) 迭代器与组合模式(Iterator & Composite pattern) C++实现
- js数组的内部实现,迭代器,生成器和内包
- Iterator和listIterator的区别 迭代器
- 《GOF设计模式》—迭代器 (ITERATOR)—Delphi源码示例:内部迭代器(依赖于子类)
- 《GOF设计模式》—迭代器 (ITERATOR)—Delphi源码示例:内部迭代器(使用函数指针)
- ArrayList利用迭代器Iterator遍历方法实现数据(新闻)的删除、添加、显示功能例子
- 迭代器,iterator的最简单实现
- 《GOF设计模式》—迭代器 (ITERATOR)—Delphi源码示例:避免限定于一种特定的列表实现(多态迭代)
- PHP:迭代器(Iterator)接口实现
- 模仿STL,实现二叉搜索数,带迭代器 BinSearchTree (iterator)
- 从零开始学C++之STL(三):迭代器类vector::iterator 和 vector::reverse_iterator 的实现、迭代器类型、常用的容器成员