1.为什么要使用迭代器模式
通过ArrayList的get方法可以很容易的将集合中的每个元素遍历出来,但是如果要获取hastSet的元素就比较麻烦了,需要掌握链表,数组甚至红黑树的遍历方式,所以为了方便将hastSet的元素遍历出来,jdk提供了一种迭代器的形式,这种设计就是现在要说的迭代器模式。
2.定义
提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
3.主要角色
3.1 抽象迭代器
定义访问和遍历聚合元素的接口,一般包含hasNext()和next()等方法
3.2 具体迭代器
用于访问和遍历聚合元素
3.3 抽象集合
定义增加,删除等操作集合元素的接口和创建迭代器的接口
3.4 具体集合
实现增加,删除等操作集合元素和创建迭代器的方法
4.场景
设计一个图集对象,要求正向播放图片
4.1 抽象迭代器
public interface Iterator<T> {
/**
* 是否有下一个元素
* @return
*/
boolean hasNext();
/**
* 下一个元素
* @return
*/
T next();
}
4.2 抽象集合
public interface IGallery {
void add(Picture picture);
void remove(Picture picture);
Iterator<Picture> iterator();
}
@Data
@AllArgsConstructor
public class Picture {
private String name;
}
4.3 具体集合
public class Gallery implements IGallery {
private List<Picture> pictures;
Gallery() {
pictures = new ArrayList<>();
}
public void add(Picture picture) {
pictures.add(picture);
}
public void remove(Picture picture) {
pictures.remove(picture);
}
public Iterator<Picture> iterator() {
Gallery gallery = new Gallery();
// 创建快照,防止获取元素异常
gallery.pictures = new ArrayList<>(this.pictures);
return new ForwardIterator(gallery);
}
private class ForwardIterator implements Iterator<Picture> {
private List<Picture> pictures;
private int curPos; // 当前指针位置
ForwardIterator(Gallery gallery) {
pictures = gallery.pictures;
curPos = -1;
}
@Override
public boolean hasNext() {
return curPos < pictures.size()-1;
}
@Override
public Picture next() {
return pictures.get(++curPos);
}
}
}
4.4 测试
public class TestGallery {
public static void main(String[] args) {
Gallery gallery = new Gallery();
gallery.add(new Picture("picture1"));
gallery.add(new Picture("picture2"));
Iterator iterator = gallery.iterator();
System.out.println("============向后遍历元素开始============");
while(iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("============向后遍历元素结束============");
}
}
----------------------------console
第一个元素:Picture(name=picture1)
最后一个元素:Picture(name=picture2)
============向后遍历元素开始============
Picture(name=picture1)
Picture(name=picture2)
============向后遍历元素结束============
============向后遍历元素开始============
============向后遍历元素结束============
5.jdk自带迭代器
上面的Iterator类在jdk存在类似的类java.util.Iterator,我们可以将上面的Iterator替换为java.util.Iterator,代码也是可以正常运行的,而且还可以实现一个更神奇的功能。一般遍历集合都会使用foreach语句,比如:
for(Object ele : list){
// .....
}
只要实现了java.lang.Iterable,这里的Gallery类也可以实现一样的效果。修改后的代码如下:
public class Gallery implements IGallery,Iterable<Picture> {
private List<Picture> pictures;
Gallery() {
pictures = new ArrayList<>();
}
public void add(Picture picture) {
pictures.add(picture);
}
public void remove(Picture picture) {
pictures.remove(picture);
}
public Iterator<Picture> iterator() {
Gallery gallery = new Gallery();
gallery.pictures = new ArrayList<>(this.pictures);
return new ForwardIterator(gallery);
}
private class ForwardIterator implements Iterator<Picture> {
private List<Picture> pictures;
private int curPos; // 当前指针位置
ForwardIterator(Gallery gallery) {
pictures = gallery.pictures;
curPos = -1;
}
@Override
public boolean hasNext() {
return curPos < pictures.size()-1;
}
@Override
public Picture next() {
return pictures.get(++curPos);
}
}
}
测试代码:
public class TestGallery {
public static void main(String[] args) {
Gallery gallery = new Gallery();
gallery.add(new Picture("picture1"));
gallery.add(new Picture("picture2"));
for(Picture picture : gallery){
System.out.println(picture);
}
}
}
----------------------------console
Picture(name=picture1)
Picture(name=picture2)