我正在参加「掘金·启航计划」
迭代器模式的核心在于: 一个一个的遍历集合中的元素
核心的方法在于hasNext()和next()两个方法:
hasNext( ): 判断集合中是否还有下一个元素, 如果有就返回true,没有就返回false
next( ): 返回当前的元素,并指向下一个元素
Iterator模式中的主要角色:
-
Iterator(迭代器)
负责按序顺序逐个遍历元素的接口,它里面定义了hasNext()和next()方法, 其中hasNext方法用于判断是否存在下一个元素,next方法则用于获取该元素
-
ConcreteIterator(具体的迭代器)
负责实现Iterator角色定义的接口, 这个角色中包含了遍历集合所需的信息(hasNext方法和next方法)
-
Aggregate(集合)
负责定义窗机Iterator角色的接口,这个接口是一个方法,可以创建出"按照顺序访问保存在集合中的元素",
-
ConcreteAggregate(具体的集合)
负责实现Aggregate角色所定义的接口,它可以创建出具体的Iterator角色,即具体的ConcreteIterator角色
接下来我们做个案例加深对他的理解:
假设有一个书架(集合)上面有若干本书(元素),现在需要遍历它!
当然for循环,for-each我们就说了,其实for-each也是Iterator,反编译后可以看到的,JDK1.8之后,Iterator接口中也增加了foeEach()方法 (就此打住了, 继续!)
1> 新建一个Book类
public class Book {
private String name;
public Book(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2> 创建一个Aggregate接口,创建一个iterator方法,用于生成一个用于遍历集合的迭代器
/**
* 集合接口
*/
public interface Aggregate {
/*创建一个iterator方法,用于生成一个用于遍历集合的迭代器*/
Iterator itarator();
}
3> 创建一个Iterator 接口 用于遍历集合中的元素,其作用相当于循环语句中变量
public interface Iterator {
/**
* 判断是否存在下一个元素
* @return 存在返回true,不存在返回false
*/
boolean hasNext();
/**
* 获取下一个元素
* @return Object
*/
Object next();
}
4> 创建一个BookShelf书架类;要把书架理解成一个装书的集合,且需要提供一个遍历集合的迭代器,所以需要实现Aggregate接口
public class BookShelf implements Aggregate {
private ArrayList<Book> books;
private int last=0;
public BookShelf(int index) {
this.books = new ArrayList<>(index);
}
//根据下标找书
public Book getBookAt(int index){
return books.get(index);
}
//往集合中添加书
public void appendBook(Book book){
books.add(book);
last++;
}
//获取集合中书的数量
public int getLength(){
return last;
}
//获取遍历书架的迭代器
@Override
public Iterator itarator() {
return new BookShelfIterator(this);
}
}
5> 创建BookShelfIterator类实现Iterator接口, 即创建一个能够遍历书架的迭代器
//因为需要实现能够遍历书架的迭代器,所以需要实现Iterator接口
public class BookShelfIterator implements Iterator {
private BookShelf bookShelf; //需要遍历的类
private int index; //遍历开始位置
public BookShelfIterator(BookShelf bookShelf) {
this.bookShelf=bookShelf;
this.index=0;
}
@Override
public boolean hasNext() {
//判读当前下标是否小于集合的大小,小于表示还有下一位元素,等于或大于表示没有下一位元素
return index < bookShelf.getLength();
}
@Override
public Object next() {
//获取对应下标的元素
Book book = bookShelf.getBookAt(index);
//下标后移一位
index++;
return book;
}
}
6> 测试
public class IteratorTest {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf(4);
bookShelf.appendBook(new Book("A_西游记"));
bookShelf.appendBook(new Book("B_红楼梦"));
bookShelf.appendBook(new Book("C_水浒传"));
bookShelf.appendBook(new Book("D_三国演义"));
Iterator itarator = bookShelf.itarator();
while (itarator.hasNext()){
Book book = (Book) itarator.next();
System.out.println(book.getName());
}
}
}
到这里应该能对迭代器模式能有一定的理解了:
大白话来说, 定义一个集合类实现集合接口(Aggregate), 而这个接口定义了一个返回遍历该集合的迭代器的方法, 每个实现了该接口的集合都必须拥有一个放回遍历自身迭代器的方法; 所以案例中BookShelf书架类实现了Aggregate接口,并在iterator方法中返回了BookShelfIterator迭代器对象; 而BookShelfIterator迭代器对象需要实现迭代的具体功能所以需要实现Iterator接口,实现接口中迭代器的具体方法;通过循环hasNext()和next()方法实现遍历;
那么我们来思考几个问题:
1、为什么一定要加使用Aggregate接口和Iterator接口,两个接口呢?如下:
修改Aggregate接口
public interface Aggregate {
/*创建一个iterator方法,用于生成一个用于遍历集合的迭代器*/
// Iterator itarator();
/**
* 判断是否存在下一个元素
* @return 存在返回true,不存在返回false
*/
boolean hasNext();
/**
* 获取下一个元素
* @return Object
*/
Object next();
}
修改BookShelf类
public class BookShelf implements Aggregate {
private ArrayList<Book> books;
private int last=0;
private int index=0;
........
//获取遍历书架的迭代器
/* @Override
public Iterator itarator() {
return new BookShelfIterator();
}*/
@Override
public boolean hasNext() {
//判读当前下标是否小于集合的大小,小于表示还有下一位元素,等于或大于表示没有下一位元素
return index < this.getLength();
}
@Override
public Object next() {
//获取对应下标的元素
Book book = this.getBookAt(index);
//下标后移一位
index++;
return book;
}
}
测试
public class IteratorTest {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf(4);
bookShelf.appendBook(new Book("西游记"));
bookShelf.appendBook(new Book("红楼梦"));
bookShelf.appendBook(new Book("水浒传"));
bookShelf.appendBook(new Book("三国演义"));
while (bookShelf.hasNext()){
Book book = (Book) bookShelf.next();
System.out.println(book.getName());
}
}
}
只用Aggregate接口同样的能实现对应的功能,还可以省去BookShelfIterator类,为什么不这样写呢?
这个我是有点不明白的~ ~ ~ 才疏学浅~ ~ ~
哪位大佬可以指点一下!
\