大家好,又见面了,我是全栈君。
套路要深…
故事背景
今天要介绍一下迭代器,首先简单说明一下,什么是迭代器,为什么要使用迭代器。
迭代器(Iterate) 的意思就是反复做某件事情。
那为什么要反复做某件事情呢,比如我们有个容器里面装了很好东西(这些东西都是同一类型的),要从容器中取每一个东西出来,就要反复去做一个取出的事情。
故事主角
迭代器模式 : 提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
在迭代器模式结构中包含聚合和迭代器两个层次结构,并在迭代器中使用到了工厂方法模式。
在迭代器结构图中有如下几个角色:
- Iterator (抽象迭代器): 定义了访问和遍历元素的接口。
- ConcreteIterator(具体的迭代器):实现了抽象迭代器接口,完成对聚合对象的遍历操作。
- Aggregate(抽象的聚合类):存储和管理元素对象,声明一个创建迭代器的方法。充当抽象迭代器工厂的角色。
- ConcreteAggregate(具体的聚合类):实现了抽象聚会类申明的创建迭代器方法。
武功修练
通过上面对迭代器的了解和认识我们看一下Java集合框架中迭代器的使用。主要看一下ArrayList、LinkedList、HashSet。这三个是集合中的三个常用类,但是它们的实现机制是不一样的。这里对实现机制就不进行讲解,不懂的朋友可以自行查找资料。
首先看一下这三个类的结构图:
其中都是实现了 Iterable接口。下面我们再看一下这个Iterable
接口
// 这个就是Aggregate(抽象的聚合类)
public interface Iterable<T> {
// 申明 创建迭代器的方法
Iterator<T> iterator();
// 其他默认实现
default void forEach(Consumer<? super T> var1) {
Objects.requireNonNull(var1);
Iterator var2 = this.iterator();
while(var2.hasNext()) {
Object var3 = var2.next();
var1.accept(var3);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(this.iterator(), 0);
}
}
在来看一下Iterator
接口
// Iterator (抽象迭代器)
public interface Iterator<E> {
boolean hasNext(); // 是否有下一个元素
E next();//下一个元素
// 其他默认实现
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> var1) {
Objects.requireNonNull(var1);
while(this.hasNext()) {
var1.accept(this.next());
}
}
}
从上面的;类图和源码中,可以看到ArrayList、LinkedList、HashSet,是ConcreteAggregate(具体的聚合类),具体的聚合类中实现创建迭代器以及实现具体的迭代器!
如下是ArrayList
源码:
// 在ArrayList创建了一个迭代器
public Iterator<E> iterator() {
return new Itr();
}
/** * An optimized version of AbstractList.Itr * jdk1.8版本 */
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
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();
}
}
// 其他方法
}
如下是LinkedList
实现迭代器的部分代码:
public Iterator<E> descendingIterator() {
return new LinkedList.DescendingIterator();
}
private class DescendingIterator implements Iterator<E> {
private final LinkedList<E>.ListItr itr;
private DescendingIterator() {
this.itr = LinkedList.this.new ListItr(LinkedList.this.size());
}
public boolean hasNext() {
return this.itr.hasPrevious();
}
public E next() {
return this.itr.previous();
}
public void remove() {
this.itr.remove();
}
}
hashSet的源码实现就不进行说明了,感兴趣的朋友可以自行查看。
通过上面简单的类图和源码分析,发现了这几个类使用了迭代器模式。
举个简单的小例子说明一下迭代器的好处:
class IteratorDemo {
public static void process(Collection c) {
Iterator i = c.iterator(); //创建迭代器对象
//通过迭代器遍历聚合对象
while(i.hasNext()) {
System.out.println(i.next().toString());
}
}
public static void main(String args[]) {
Collection persons;
persons = new ArrayList(); //创建一个ArrayList类型的聚合对象
persons.add("2");
persons.add("5");
persons.add("3");
persons.add("7");
persons.add("0");
persons.add("4");
process(persons);
}
}
如果需要更换聚合类型,如将List改成Set即可,迭代遍历的代码无需进行修改。
总结
迭代器模式简化了聚合类对象的元素的遍历,封装了聚合类具体的遍历实现细节,能够实现聚合对象的内部数据和存储分离,使得聚合类的职责更加专一,同时提供统一的接口,方便客户端操作。
Next 期待下一篇吧!下一篇讲讲组合模式!
参考
- 史上最全设计模式导学
- 《Head First 设计模式》
- 《图解设计模式》
本专栏文章列表
一、设计模式-开篇—为什么我要去旅行? #和设计模式一起旅行#
二、设计模式-必要的基础知识—旅行前的准备 #和设计模式一起旅行#
三、设计模式介绍—她是谁,我们要去哪里? #和设计模式一起旅行#
四、单例模式—不要冒充我,我只有一个! #和设计模式一起旅行#
五、工厂模式—旅行的钱怎么来 #和设计模式一起旅行#
六、策略模式—旅行的交通工具 #和设计模式一起旅行#
七、观察者模式——关注我,分享旅途最浪漫的瞬间! #和设计模式一起旅行#
八、装饰者模式—巴厘岛,奶茶店的困扰! #和设计模式一起旅行#
九、命令模式—使用命令控制奶茶店中酷炫的灯 #和设计模式一起旅行#
十、模板方法模式—制作更多好喝的饮品! #和设计模式一起旅行#
十一、代理模式 —专注,做最好的自己!#和设计模式一起旅行#
十二、适配器模式——解决充电的烦恼 #和设计模式一起旅行#
十三、外观模式—— 简化接口 #和设计模式一起旅行#
十四、迭代器模式—— 一个一个的遍历 #和设计模式一起旅行#
十五、组合模式—— 容器与内容的一致性 #和设计模式一起旅行#
十六、状态模式—用类表示状态 #和设计模式一起旅行#
十七、访问者模式-访问数据结构并处理数据 #和设计模式一起旅行#
十八、职责链模式-推卸责任,不关我的事,我不管!#和设计模式一起旅行#
十九、原型模式—通过复制生产实例 #和设计模式一起旅行#
二十、设计模式总结—后会有期 #和设计模式一起旅行#
如果您觉得这篇博文对你有帮助,请点赞或者喜欢,让更多的人看到,谢谢!
如果帅气(美丽)、睿智(聪颖),和我一样简单善良的你看到本篇博文中存在问题,请指出,我虚心接受你让我成长的批评,谢谢阅读!
祝你今天开心愉快!
欢迎访问我的csdn博客,我们一同成长!
不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!
博客首页 : http://blog.csdn.net/u010648555
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/121088.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...