网站首页 > java教程 正文
迭代器模式(Iterator Design Pattern)是一种行为型模式,它提供了一种访问容器对象中各个元素的方法,而且不需要了解容器对象内部实现结构。
迭代器模式分离了聚集对象的遍历行为,抽象出迭代器类负责具体迭代过程,从而可以使得聚集对象更容易的被复用。
在本篇文章中,我将详细阐述迭代器模式的原理、使用场景以及示例,希望能够帮助读者更好的理解和掌握该模式。
一、迭代器模式原理
迭代器模式主要由以下几个角色组成:
1、迭代器(Iterator):定义访问和遍历元素的接口,具体迭代器负责实现这些接口。
2、具体迭代器(Concrete Iterator):具体实现迭代器接口中的方法,完成对聚集对象的遍历。
3、聚集对象(Aggregate):定义创建迭代器的接口,即工厂方法,具体聚集对象返回相应的具体迭代器实例。
4、具体聚集对象(Concrete Aggregate):实现聚集对象接口,返回一个具体迭代器实例。
我们可以通过一个简单的示例来更好的理解迭代器模式。
假设我们要实现一个简单的数列,包括添加元素、删除元素和遍历元素等功能。这时我们可以使用迭代器模式来达到这个目的。
首先,我们定义一个迭代器接口:
public interface Iterator {
boolean hasNext(); // 是否还有下一个元素
Object next(); // 返回下一个元素
}
然后,我们定义一个聚集对象接口:
public interface Aggregate {
void add(Object obj); // 添加元素
void remove(Object obj); // 删除元素
Iterator createIterator(); // 创建迭代器
}
接下来,我们实现具体迭代器类:
public class ConcreteIterator implements Iterator {
private List<Object> list; // 数列
private int index = 0; // 当前元素下标
public ConcreteIterator(List<Object> list) {
this.list = list;
}
@Override
public boolean hasNext() {
if (index < list.size()) {
return true;
}
return false;
}
@Override
public Object next() {
Object obj = null;
if (hasNext()) {
obj = list.get(index++);
}
return obj;
}
}
最后,我们实现具体聚集对象类(代码如下):
public class ConcreteAggregate implements Aggregate {
private List<Object> list = new ArrayList<>();
@Override
public void add(Object obj) {
list.add(obj);
}
@Override
public void remove(Object obj) {
list.remove(obj);
}
@Override
public Iterator createIterator() {
return new ConcreteIterator(list);
}
}
现在,我们就可以使用迭代器模式来实现数列的遍历功能了,示例代码如下:
public class IteratorPatternDemo {
public static void main(String[] args) {
Aggregate aggregate = new ConcreteAggregate();
aggregate.add("元素A");
aggregate.add("元素B");
aggregate.add("元素C");
aggregate.add("元素D");
Iterator iterator = aggregate.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
执行上述代码后,我们就可以看到数列中所有的元素被遍历输出了。
二、Java源码中的迭代器模式
在我们使用非常频繁的 Java 集合中,就使用了迭代器模式。下面以常用的 ArrayList 集合部分源码讲解 Java 实现迭代器模式的方式。
首先,在 Java 源码的 java.util.Iterator 类中定义了迭代器的基本接口方法,hasNext、next、remove。源码如下:
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
.....
}
然后,在 ArrayList 中,定义了一个内部类 Itr 实现了 Iterator 接口。源码如下:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
......
public Iterator<E> iterator() {
// 返回一个迭代器对象
return new Itr();
}
/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
int cursor; // 下一个待返回元素的位置
int lastRet = -1; // 最后一次返回元素的位置; 如果没有则为-1
int expectedModCount = modCount; // 集合结构修改次数
public boolean hasNext() {
// 判断是否还有下一个元素
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
// 获取下一个元素并移动游标
checkForComodification(); // 检查集合是否被修改过
int i = cursor;
if (i >= size)
throw new NoSuchElementException(); // 抛出异常,表示没有下一个元素
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException(); // 抛出异常,表示集合的结构被修改
cursor = i + 1;
return (E) elementData[lastRet = i]; // 返回下一个元素
}
public void remove() {
// 删除当前迭代器返回的元素
if (lastRet < 0)
throw new IllegalStateException(); // 抛出异常,表示没有上一个元素
checkForComodification(); // 检查集合是否被修改过
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount; // 修改集合结构次数
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException(); // 抛出异常,表示集合的结构被修改
}
}
......
}
......
}
从上面代码可以看到,使用 iterator() 方法可以获取到一个迭代器对象,使用这个迭代器对象就可以变量集合里的元素。
值得一提的是,remove() 方法中的下面这一行代码
expectedModCount = modCount; // 修改集合结构次数
这一行代码的作用,使在用迭代器遍历集合的同时,又对集合元素进行删除操作,不会在遍历下一个元素时抛出 ConcurrentModificationException 异常。这里又是一个面试经常会问到的问题。
三、总结
通过本篇文章的讲解,我们可以看出迭代器模式的优点,它将聚集对象中各个元素的遍历行为进行了分离,从而使得聚集对象更容易被复用。同时,该模式也十分符合Java的设计原则,即“面向接口编程”,这样一来,我们可以为同一个聚集对象定义不同的迭代器,以满足不同的需求。
当然,迭代器模式也有一些缺点,例如其可扩展性不太好,迭代器只能依次访问聚集对象中的各个元素,在某些情况下,这可能会导致效率低下。此外,对于一些简单的聚集对象,使用迭代器模式也可能会增加代码的复杂性。
总的来说,迭代器模式在Java中的应用是非常广泛的,它可以帮助我们更好的管理和遍历聚集对象中的各个元素,提高代码的可读性和可维护性,同时也充分体现了Java语言的面向对象特性和设计原则。
对于本文中的内容,不知道你有没有什么看法,欢迎在评论区里留言。如果你对我的文章内容感兴趣,欢迎点击关注,谢谢支持![谢谢][谢谢][谢谢]
猜你喜欢
- 2025-01-10 Java 中经常被提到的 SPI 到底是什么?
- 2025-01-10 23种设计模式总结详解(全23种)
- 2025-01-10 Java 中的反应式编程 (RxJava)
- 2025-01-10 Java Stream
- 2025-01-10 推荐给 Java 初学者硬核书籍,亲身经历让你少走弯路
- 2025-01-10 Spring Boot集成AJ-Captcha实现滑动验证码功能
- 2025-01-10 java.util.ArrayList 原理详细介绍
- 2025-01-10 Java ArrayList用法详解附代码示例
- 2025-01-10 Java SPI详解
- 2025-01-10 Qt——容器类
你 发表评论:
欢迎- 04-24Java Collections 工具类集合框架中常用算法解析
- 04-24桶排序的简单理解
- 04-24Java集合框架底层实现原理大揭秘
- 04-24Java 集合框架全面解析:选对数据结构,提升开发效率
- 04-24c#集合排序
- 04-24Java面试中常被问到的集合类深度解读
- 04-24VBA技术资料MF278:对集合进行排序
- 04-24Spring 最常用的 7 大类注解,史上最强整理
- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)