十四、迭代器模式—— 一个一个的遍历 #和设计模式一起旅行#「建议收藏」

套路要深…故事背景今天要介绍一下迭代器,首先简单说明一下,什么是迭代器,为什么要使用迭代器。 迭代器(Iterate) 的意思就是反复做某件事情。那为什么要反复做某件事情呢,比如我们有个容器里面装了很好东西(这些东西都是同一类型的),要从容器中取每一个东西出来,就要反复去做一个取出的事情。故事主角迭代器模式 : 提供一种方法顺序访问一个聚合对象中的各个元素,而…

大家好,又见面了,我是全栈君。

套路要深…

故事背景

今天要介绍一下迭代器,首先简单说明一下,什么是迭代器,为什么要使用迭代器。
迭代器(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 期待下一篇吧!下一篇讲讲组合模式!

参考

本专栏文章列表

一、设计模式-开篇—为什么我要去旅行? #和设计模式一起旅行#
二、设计模式-必要的基础知识—旅行前的准备 #和设计模式一起旅行#
三、设计模式介绍—她是谁,我们要去哪里? #和设计模式一起旅行#
四、单例模式—不要冒充我,我只有一个! #和设计模式一起旅行#
五、工厂模式—旅行的钱怎么来 #和设计模式一起旅行#
六、策略模式—旅行的交通工具 #和设计模式一起旅行#
七、观察者模式——关注我,分享旅途最浪漫的瞬间! #和设计模式一起旅行#
八、装饰者模式—巴厘岛,奶茶店的困扰! #和设计模式一起旅行#
九、命令模式—使用命令控制奶茶店中酷炫的灯 #和设计模式一起旅行#
十、模板方法模式—制作更多好喝的饮品! #和设计模式一起旅行#
十一、代理模式 —专注,做最好的自己!#和设计模式一起旅行#
十二、适配器模式——解决充电的烦恼 #和设计模式一起旅行#
十三、外观模式—— 简化接口 #和设计模式一起旅行#
十四、迭代器模式—— 一个一个的遍历 #和设计模式一起旅行#
十五、组合模式—— 容器与内容的一致性 #和设计模式一起旅行#
十六、状态模式—用类表示状态 #和设计模式一起旅行#
十七、访问者模式-访问数据结构并处理数据 #和设计模式一起旅行#
十八、职责链模式-推卸责任,不关我的事,我不管!#和设计模式一起旅行#
十九、原型模式—通过复制生产实例 #和设计模式一起旅行#
二十、设计模式总结—后会有期 #和设计模式一起旅行#


如果您觉得这篇博文对你有帮助,请点赞或者喜欢,让更多的人看到,谢谢!

如果帅气(美丽)、睿智(聪颖),和我一样简单善良的你看到本篇博文中存在问题,请指出,我虚心接受你让我成长的批评,谢谢阅读!
祝你今天开心愉快!


欢迎访问我的csdn博客,我们一同成长!

不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!

博客首页 : http://blog.csdn.net/u010648555

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/121088.html原文链接:https://javaforall.net

(0)
上一篇 2022年2月27日 下午1:00
下一篇 2022年2月27日 下午2:00


相关推荐

  • 设计模式之责任链模式(职责链模式)

    设计模式之责任链模式(职责链模式)前言在现实生活中 一个事件需要经过多个对象处理是很常见的场景 例如 采购审批流程 请假流程等 公司员工请假 可批假的领导有部门负责人 副总经理 总经理等 但每个领导能批准的天数不同 员工必须根据需要请假的天数去找不同的领导签名 也就是说员工必须记住每个领导的姓名 电话和地址等信息 这无疑增加了难度 在计算机软硬件中也有相关例子 如总线网中数据报传送 每台计算机根据目标地址是否同自己的地址相同来决定是否接收 还有异常处理中 处理程序根据异常的类型决定自己是否处理该异常 还有 Struts2 的拦截器 J

    2026年3月18日
    1
  • 设计模式 – 结构型设计模式 – 适配器模式(Java)

    设计模式 – 结构型设计模式 – 适配器模式(Java)分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.netDefinitionSeparatetheconstructionofacomplexobjectfromitsrepresentationsothatthesameconstructionprocesscan…

    2022年7月25日
    14
  • 设计模式、框架、架构、平台的区别「建议收藏」

    设计模式、框架、架构、平台的区别「建议收藏」区分什么是架构、框架、模式和平台,一直都感觉这几个词过于抽象和模糊,今天大家来说说到底什么是架构、框架、模式和平台? 收集了的一些来自网上各自的定义和区分如下: 设计模式 1、设计模式为什么要先说设计模式?因为设计模式在这些概念中是最基本的,而且也比较简单。那么什么是设计模式呢?说的直白点,设计模式就是告诉你针对特定问题如何组织类、对象和接口之间的关系,是前人总结的经验

    2022年10月10日
    4
  • 什么是Web 2.0——下一代软件的设计模式和商业模式 (全文翻译—1 博客版序)

    什么是Web 2.0——下一代软件的设计模式和商业模式 (全文翻译—1 博客版序)这篇文章,是经O’Reilly公司的TimO’Reilly先生授权后,进行全文翻译、出版的。包括:杂志节选版和网络全文版。转载:请遵循CC版权,保留原文作者和翻译作者信息,以及文章链接。感谢:互联网周刊的李洋提供了许多建议。几个文章版本链接:英文原文:http://www.oreillynet.com/pub/a/oreilly/tim/news/2005/09/30/

    2022年7月21日
    15
  • Java设计模式之行为型:观察者模式

    Java设计模式之行为型:观察者模式

    2021年10月4日
    47
  • 设计模式之观察者模式建议收藏

    在日常生活中,交通信号灯指挥者日益拥挤的城市交通。红灯亮,汽车停止;绿灯亮,汽车继续前行;在这个过程中,交通信号灯是汽车的观察目标,而汽车则是观察者。随着交通信号灯的变化,汽车的行为也会随之变化,一盏

    2021年12月19日
    54

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号