Java设计模式---迭代器模式(Iterator)解读

2025-06-30 17:50

本文主要是介绍Java设计模式---迭代器模式(Iterator)解读,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,...

迭代器(Iterator)是一种常见的设计模式,它提供了一种统一的访问集合元素的方式,同时隐藏了集合的内部实现细节

注意⚠️:蓝色为继承、黄色为接口实现。

Java设计模式---迭代器模式(Iterator)解读

由上图可知:

  • 1、 在集合的顶端为Iterable接口。
  • 2、对于AbstractList<E> extends AbstractCollection<E>,两者均属于抽象类分别实现List接口和Collection接口。而List接口继承于Collection接口。
  • 3、关于其他子实现均实现AbstractList,AbstractCollection。
  • 4、对于queue接口。和List一样,继承Collection接口。

1、迭代器(Iterator)

迭代器是一种对象,它允许你按顺序访问一个聚合对象(如列表、树、图等)中的元素,而无需暴露集合的内部结构

1.1、结构

关于Collection接口,继承于Iterable接口。

Java 的集合框架(如List、Set)均实现了Iterator接口,通过iterator()方法返回迭代器:

代码示例如下:

public interface Collection<E> extends Iterable<E> {}

public interface Iterable<T> {
    Iterator<T> iterator();
}

通过迭代器模式,可以将集合的遍历逻辑与集合本身的实现解耦,从而提高代码的灵活性和可维护性。

1.2、常用方法

它通常包含以下核心方法:

  • hasNext():判断是否还有下一个元素。
  • next():获取下一个元素。
  • remove()(可选):删除当前元素。

代码示例:

List<String> list = Arrays.asList("A", "B", "C");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

1.3、本质

迭代器被归类java设计模式里面的行为型设计模式(Behavioral Design Pattern),定义了对象之间的交互方式

它的核心思想是:

解耦遍历逻辑与数据结构,使客户端无需关心数据的存储方式即可统一访问元素。

1、解耦集合与遍历逻辑

  • 传统方式:直接通过索引遍历集合(如数组),客户端需要知道集合的内部结构(如数组长度)。
  • 迭代器方式:客avbDRd户端只需调用hasNext()和next(),无需关心集合是数组、链表还是树。

2、统一访问接口

  • 不同类型的集合(如List、Set、Map)可以提供自己的迭代器实现,客户端通过统一的Iterator接口操作。

3、支持多种遍历方式

  • 迭代器可以定义不同的遍历策略(如正向、逆向、深度优先搜索等),而集合本身不需要修改。

4、提高代码复用性

  • 迭代器模式将遍历逻辑抽象为独立的对象,可以被多个集合复用。

1.4、自定义迭代器

// 自定义集合
class MyCollection implements Iterable<Integer> {
    private List<Integer> data = new ArrayList<>();

    public void add(int value) {
        data.add(value);
    }

    @Override
    public Iterator<Integer> iterator() {
       js return new MyIterator();
    }

    // 自定义迭代器
    private class MyIterator implements Iterator<Integer> {
        private int index = 0;

        @Override
        public boolean hasNext() {
            return index < data.size();
        }

        @Override
        public Integer next() {
            return data.get(index++);
        }
    }
}

总结

Java设计模式---迭代器模式(Iterator)解读

2、迭代器模式的组成

2.1、迭代器模式角色

1、抽象迭代www.chinasem.cn器(Iterator):

定义了遍历聚合对象所需的方法,包括hashNext()和next()方法等,用于遍历聚合对象中的元素。

2、具体迭代器(Concrete Iterator):

它是实现迭代器接口的具体实现类,负责具体的遍历逻辑。它保存了当前遍历的位置信息,并可以根据需要向前或向后遍历集合元素。

3、抽象聚合器(Aggregate):

一般是一个接口,提供一个iterator()方法,例如java中的Collection接口,List接口,Set接口等。

4、具体聚合器(ConcreteAggregate):

就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,Set接口的哈希列表的实现HashSet等。

2.2、UML 类图

如下所示:

Java设计模式---迭代器模式(Iterator)解读

2.3、举例

下面以班级名单为例,解释一下迭代器模式。

  • 抽象迭代器:StudentIterator
  • 具体迭代器:StudentListIterator
  • 抽象聚合器:StudentAggregate
  • 具体聚合器:ClassList

Java设计模式---迭代器模式(Iterator)解读

1、Student——学生实体类

首先定义一个学生类,用来表示学生信息。

如下图所示:

/**
 * @author Created by njy on 2023/6/25
 * 学生实体类
 */
@Data
public class Student {
    private String name;
    private Integer age;
    public Student(String name,Integer age){
        this.age=age;
        this.name=name;
    }
}

2、StudentIterator——抽象迭代器(Iterator)

创建一个抽象迭代器(学生迭代器)并继承Iterator接口(java.util包下的Iterator)。

如下所示:

import java.util.Iterator;
/**
 * @author Created by njy on 2023/6/25
 * 抽象迭代器(Iterator):学生迭代器
 * 实现Iterator接口
 * 负责定义访问和遍历元素的接口,例如提供hasNext()和next()方法。
 */
public interface StudentIterator extends Iterator<Student> {
}

3、StudentListIterator——具体迭代器(Concrete iterator)

在这个具体迭代器中,实现抽象迭代器,重写hashNext()和next()方法。

如下所示:

/**
 * @author Created by njy on 2023/6/25
 * 具体迭代器(Concrete iterator):
 * 实现抽象迭代器定义的接口,负责实现对元素的访问和遍历。
 */
public class StudentListIterator implements StudentIterator{
    private List<Student> students;
    private int index;
 
    public StudentListIterator(List<Student> students) {
        this.students = students;
        this.index = 0;
    }
 
    //检查是否还有下一个元素
    @Override
    public boolean hasNext() {
        return (index < students.size());
    }
 
    //返回下一个元素
    @Override
    public Student next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        Student student = students.get(index);
        index++;
        return student;
    }
}

4、StudentAggregate——抽象聚合器(Aggregate)

定义一个抽象聚合器,并定义一个iterator()方法,用于创建具体的迭代器对象。

如下所示:

/**
 * @author Created by njy on 2023/6/25
 * 抽象聚合器(Aggregate):学生聚合器
 * 提供创建迭代器的接口,例如可以定义一个iterator()方法。
 */
public interface StudentAggregate {
    //用于创建具体的迭代器对象
    StudentIterator iterator();
    void add(Student student);
}

5、ClassList——具体聚合器(Concrete Aggregate)

实现抽象聚合器定义的接口,负责创建具体的迭代器对象。

如下所示:

/**
 * @author Created by njy on 2023/6/25
 * 具体聚合器www.chinasem.cn(ConcreteAggregate):班级列表
 * 实现抽象聚合器定义的接口,负责创建具体的迭代器对象,并返回该对象。
 */
public class ClassList implements StudentAggregate{
    private List<Student> students = new ArrayList<>();
 
    //创建迭代器对象
    @Override
    public StudentIterator iterator() {
        return new StudentListIterator(students);
    }
 
    //向班级名单中添加学生信息
    @Override
    public void add(Student student) {
        students.add(student);
    }
}

6、testIterator

/**
 * @author Created by njy on 2023/6/25
 * 迭代器模式测试类
 */
@SpringBootTest
public class TestIterator {
    @Test
    void testIterator(){
        ClassList classList = new ClassList();
        // 添加学生信息
        classList.add(new Student("张三", 18));
        classList.add(new Student("李四", 19));
        classList.add(new Student("王五", 20));
        // 获取迭代器,遍历学生信息
        StudentIterator iterator = classList.iterator();
        while(iterator.hasNext()) {
            Student student = iterator.next();
            System.out.println("学生姓名:" + student.getName() + ",学生年龄:" + student.getAge());
        }
    }
 
}

输出:
学生姓名:张三,学生年龄:18
学生姓名:李四,学生年龄:19
学生姓名:王五,学生年龄:20

3、实际应用

1、集合框架中的迭代器:

在Java中,集合包括List、Set、Map等等,每个集合类中都提供了一个获取迭代器的方法,例如List提供的iterator()方法、Set提供的iterator()方法等等。

通过获取对应的迭代器对象,可以对集合中的元素进行遍历和访问。

代码示例:

import java.util.*;

public class CollectionIteratorExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("A", "B", "C");
        Iterator<String> iterator = list.iterator();

        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

2、JDBC中的ResultSet对象:

在Java中,如果需要对数据库中的数据进行遍历和访问,可以使用JDBC操作数据库。

JDBC中,查询结果集使用ResultSet对象来表示,通过使用ResultSet的next()方法,就可以像使用迭代器一样遍历和访问查询结果中的数据。

代码示例:

import java.sql.*;
import java.util.Iterator;

public class JdbcIteratorExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydb";
        String user = "root";
        String password = "password";

        try (Connection conn = DriverManager.getConnection(url, user, password);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT id, name FROM users")) {

            // 使用自定义迭代器遍历 ResultSet
            Iterator<User> userIterator = new ResultSetIterator<>(rs);
            while (userIterator.hasNext()) {
                User user = userIterator.next();
                System.out.println(user);
            }

        } catch (SandroidQLException e) {
            e.printStackTrace();
        }
    }

    // 自定义迭代器
    static class ResultSetIterator<T> implements Iterator<T> {
        private final ResultSet rs;
        private final RowMapper<T> rowMapper;

        public ResultSetIterator(ResultSet rs) throws SQLException {
            this.rs = rs;
            this.rowMapper = (rs1) -> {
                User user = new User();
                user.setId(rs1.getInt("id"));
                user.setName(rs1.getString("name"));
                return user;
            };
        }

        @Override
        public boolean hasNext() throws SQLException {
            return rs.next();
        }

        @Override
        public T next() throws SQLException {
            return rowMapper.mapRow(rs);
        }
    }

    // 辅助类
    static class User {
        private int id;
        private String name;

        // Getters and setters
        @Override
        public String toString() {
            return "User{" + "id=" + id + ", name='" + name + '\'' + '}';
        }
    }

    interface RowMapper<T> {
        T mapRow(ResultSet rs) throws SQLException;
    }
}

3、文件读取:

在Java中,我们可以使用BufferedReader类来读取文本文件。BufferedReader类提供了一个方法readLine()来逐行读取文件内容。

BufferedReader在内部使用了迭代器模式来逐行读取文本文件的内容。

代码示例:

import java.io.*;
import java.util.Iterator;

public class FileIteratorExample {
    public static void main(String[] args) {
        String filePath = "example.txt";

        try (FileReader reader = new FileReader(filePath);
             BufferedReader bufferedReader = new BufferedReader(reader)) {

            // 使用自定义迭代器遍历文件
            Iterator<String> lineIterator = new LineIterator(bufferedReader);
            while (lineIterator.hasNext()) {
                System.out.println(lineIterator.next());
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 自定义迭代器
    static class LineIterator implements Iterator<String> {
        private final BufferedReader reader;
        private String nextLine;

        public LineIterator(BufferedReader reader) throws IOException {
            this.reader = reader;
            this.nextLine = reader.readLine();
        }

        @Override
        public boolean hasNext() {
            try {
                return nextLine != null || (nextLine = reader.readLine()) != null;
            } catch (IOException e) {
                throw new RuntimeException("读取文件时出错", e);
            }
        }

        @Override
        public String next() {
            if (!hasNext()) {
                throw new IllegalStateException("没有更多行");
            }
            String currentLine = nextLine;
            try {
                nextLine = reader.readLine();
            } catch (IOException e) {
                throw new RuntimeException("读取文件时出错", e);
            }
            return currentLine;
        }
    }
}

4、优缺点

4.1、优点

1、隐藏集合实现细节

  • 客户端无需知道集合是链表、数组还是其他结构,只需通过迭代器操作。

2、支持并发修改

  • 某些迭代器(如 Java 的ConcurrentHashMap的弱一致性迭代器)可以处理并发修改,避免ConcurrentModificationException。可参考:集合中的并发修改异常及处理方式

3、灵活的遍历方式

  • 例如,可以为树结构定义深度优先或广度优先的迭代器。

4、代码简洁性

  • 使用迭代器可以避免重复编写遍历逻辑(如手动管理索引)。

4.2、缺点

  • 增加了代码复杂度:需要额外定义迭代器类。
  • 性能开销:对于简单集合(如数组),直接遍历可能更高效。

总结

迭代器模式是 Java 集合框架的核心设计之一,也是许多高级数据结构(如树、图)遍历的基础。通过理解其原理,可以更高效地设计和实现符合要求的集合类。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持China编程(www.chinasem.cn)。

这篇关于Java设计模式---迭代器模式(Iterator)解读的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155263

相关文章

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

SpringBoot整合liteflow的详细过程

《SpringBoot整合liteflow的详细过程》:本文主要介绍SpringBoot整合liteflow的详细过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋...  liteflow 是什么? 能做什么?总之一句话:能帮你规范写代码逻辑 ,编排并解耦业务逻辑,代码

JavaSE正则表达式用法总结大全

《JavaSE正则表达式用法总结大全》正则表达式就是由一些特定的字符组成,代表的是一个规则,:本文主要介绍JavaSE正则表达式用法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录常用的正则表达式匹配符正则表China编程达式常用的类Pattern类Matcher类PatternSynta

Spring Security中用户名和密码的验证完整流程

《SpringSecurity中用户名和密码的验证完整流程》本文给大家介绍SpringSecurity中用户名和密码的验证完整流程,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定... 首先创建了一个UsernamePasswordAuthenticationTChina编程oken对象,这是S

java实现docker镜像上传到harbor仓库的方式

《java实现docker镜像上传到harbor仓库的方式》:本文主要介绍java实现docker镜像上传到harbor仓库的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 前 言2. 编写工具类2.1 引入依赖包2.2 使用当前服务器的docker环境推送镜像2.2