开发者

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

目录
  • 1、迭代器(Iterator)
    • 1.1、结构
    • 1.2、常用方法
    • 1.3、本质
      • 1、解耦集合与遍历逻辑
      • 2、统一访问接口
      • 3、支持多种遍历方式
      • 4、提高代码复用性
    • 1.4、自定义迭代器
    • 2、迭代器模式的组成
      • 2.1、迭代器模式角色
        • 2.2、UML 类图
          • 2.3、举例
          • 3、实际应用
            • 4、优缺点
              • 4.1、优点
                • 4.2、缺点
                • 总结

                  迭代器(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.devze.com器(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.devze.com(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 集合框架的核心设计之一,也是许多高级数据结构(如树、图)遍历的基础。通过理解其原理,可以更高效地设计和实现符合要求的集合类。

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

                  0

                  上一篇:

                  下一篇:

                  精彩评论

                  暂无评论...
                  验证码 换一张
                  取 消

                  最新开发

                  开发排行榜