临桂区建设局网站,云南微网站建设,饮食网站首页页面,延吉最好的网站建设公司一、迭代器模式核心定义迭代器模式是行为型设计模式的一种#xff0c;核心目的是#xff1a;提供一种方法顺序访问一个聚合对象#xff08;如集合、容器#xff09;中的各个元素#xff0c;而又不暴露该对象的内部表示。简单来说#xff0c;就是把集合的 “遍历逻辑” 从…一、迭代器模式核心定义迭代器模式是行为型设计模式的一种核心目的是提供一种方法顺序访问一个聚合对象如集合、容器中的各个元素而又不暴露该对象的内部表示。简单来说就是把集合的 “遍历逻辑” 从集合类中抽离出来封装成独立的迭代器对象。核心解决的问题解耦遍历与集合集合只需关注 “存储元素”遍历逻辑交给迭代器符合单一职责原则统一遍历接口不同集合如数组、链表、树都可通过相同的迭代器接口遍历无需关心集合底层实现支持多线程遍历每个迭代器持有独立的遍历状态多个迭代器可同时遍历同一个集合安全遍历迭代器可控制遍历过程如禁止遍历中修改集合避免并发修改异常。生活类比场景 1图书馆借书聚合对象图书馆存储书籍迭代器借书员按编号 / 分类遍历书籍无需知道图书馆的书架布局核心你只需告诉借书员 “找所有计算机类书籍”无需自己翻书架。场景 2点餐系统聚合对象菜单存储菜品迭代器服务员按热菜 / 凉菜 / 主食遍历菜品无需知道菜单的存储格式。标准角色角色职责类比图书馆场景JDK 对应类 / 接口迭代器接口Iterator定义遍历元素的统一方法hasNext()、next()、remove()借书员的工作规范java.util.Iterator具体迭代器ConcreteIterator实现迭代器接口持有聚合对象引用记录遍历状态具体的借书员按编号遍历ArrayList.Itr、HashMap.KeyIterator聚合接口Aggregate定义创建迭代器的方法createIterator()图书馆的 “提供遍历服务” 规范java.util.Collection具体聚合ConcreteAggregate实现聚合接口返回具体迭代器实例具体的图书馆存储书籍ArrayList、HashMap、LinkedList核心 UML 类图二、自定义集合 迭代器以 “自定义书架集合” 为例实现迭代器模式的核心逻辑 —— 这是理解 JDK 集合迭代器的基础。1. 步骤 1定义迭代器接口统一遍历规范/** * 迭代器接口定义遍历书籍的统一方法 */ public interface BookIterator { /** * 判断是否有下一本书 */ boolean hasNext(); /** * 获取下一本书 */ Book next(); /** * 移除当前遍历的书可选 */ void remove(); }2. 步骤 2定义聚合接口创建迭代器/** * 聚合接口书架的统一规范定义创建迭代器的方法 */ public interface BookShelfAggregate { /** * 添加书籍 */ void addBook(Book book); /** * 删除书籍 */ void removeBook(Book book); /** * 创建迭代器核心聚合对象提供迭代器 */ BookIterator createIterator(); }3. 步骤 3实现具体聚合自定义书架import java.util.ArrayList; import java.util.List; /** * 具体聚合书架存储书籍的集合 */ public class BookShelf implements BookShelfAggregate { // 底层存储ArrayList也可替换为数组、链表等迭代器无需感知 private final ListBook books new ArrayList(); Override public void addBook(Book book) { books.add(book); } Override public void removeBook(Book book) { books.remove(book); } /** * 返回具体迭代器绑定当前书架 */ Override public BookIterator createIterator() { return new BookShelfIterator(this); } // 供迭代器访问内部元素的方法不暴露底层List public Book getBook(int index) { return books.get(index); } // 供迭代器获取集合大小 public int getSize() { return books.size(); } }4. 步骤 4实现具体迭代器书架迭代器/** * 具体迭代器书架迭代器封装遍历逻辑 */ public class BookShelfIterator implements BookIterator { // 持有聚合对象引用遍历的目标集合 private final BookShelf bookShelf; // 遍历状态当前索引 private int currentIndex 0; public BookShelfIterator(BookShelf bookShelf) { this.bookShelf bookShelf; } /** * 判断是否有下一个元素核心遍历终止条件 */ Override public boolean hasNext() { return currentIndex bookShelf.getSize(); } /** * 获取下一个元素核心移动索引并返回元素 */ Override public Book next() { if (!hasNext()) { throw new NoSuchElementException(已遍历到最后一本书); } Book book bookShelf.getBook(currentIndex); currentIndex; // 移动索引 return book; } /** * 移除当前元素需回退索引避免漏遍历 */ Override public void remove() { if (currentIndex 0) { throw new IllegalStateException(未开始遍历或已移除当前元素); } bookShelf.removeBook(bookShelf.getBook(currentIndex - 1)); currentIndex--; // 回退索引 } }5. 步骤 5书籍模型迭代的元素import lombok.AllArgsConstructor; import lombok.Data; /** * 迭代的元素书籍 */ Data AllArgsConstructor public class Book { private String isbn; // 书号 private String name; // 书名 private String author; // 作者 }6. 客户端使用迭代器遍历import java.util.NoSuchElementException; /** * 客户端使用迭代器遍历书架 */ public class IteratorClient { public static void main(String[] args) { // 1. 创建聚合对象书架并添加元素 BookShelf bookShelf new BookShelf(); bookShelf.addBook(new Book(9787111641247, Java编程思想, Bruce Eckel)); bookShelf.addBook(new Book(9787121387374, Spring实战, Craig Walls)); bookShelf.addBook(new Book(9787115546081, 设计模式之美, 王争)); // 2. 创建迭代器无需关心书架底层是List/数组 BookIterator iterator bookShelf.createIterator(); // 3. 遍历元素统一接口适配所有聚合对象 System.out.println( 遍历所有书籍 ); while (iterator.hasNext()) { Book book iterator.next(); System.out.println(书号 book.getIsbn() 书名 book.getName() 作者 book.getAuthor()); } // 4. 测试移除元素遍历中删除 System.out.println(\n 移除第二本书后重新遍历 ); BookIterator iterator2 bookShelf.createIterator(); // 跳过第一本 iterator2.next(); // 移除第二本 iterator2.remove(); // 重新遍历 while (iterator2.hasNext()) { Book book iterator2.next(); System.out.println(书号 book.getIsbn() 书名 book.getName() 作者 book.getAuthor()); } // 5. 测试遍历到末尾抛出异常 try { BookIterator iterator3 bookShelf.createIterator(); while (iterator3.hasNext()) { iterator3.next(); } iterator3.next(); // 无元素抛出异常 } catch (NoSuchElementException e) { System.out.println(\n遍历异常 e.getMessage()); } } }输出结果 遍历所有书籍 书号9787111641247书名Java编程思想作者Bruce Eckel 书号9787121387374书名Spring实战作者Craig Walls 书号9787115546081书名设计模式之美作者王争 移除第二本书后重新遍历 书号9787115546081书名设计模式之美作者王争 遍历异常已遍历到最后一本书三、Spring 实战版自定义分页迭代器在业务开发中迭代器模式最实用的场景是分页遍历大数据集合如数据库分页查询、接口分批拉取数据。以下实现一个 “数据库用户列表分页迭代器”无需一次性加载所有数据而是按需分页获取。1. 依赖准备Spring Bootdependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter/artifactId version3.2.3/version /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies2. 核心模型定义import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * 迭代的元素用户 */ Data NoArgsConstructor AllArgsConstructor public class User { private Long id; private String username; private String email; } /** * 分页查询参数 */ Data AllArgsConstructor public class PageParam { private int pageNum; // 页码从1开始 private int pageSize; // 每页条数 } /** * 分页查询结果 */ Data public class PageResultT { private int pageNum; // 当前页码 private int pageSize; // 每页条数 private long total; // 总条数 private ListT data; // 当前页数据 // 判断是否有下一页 public boolean hasNext() { return pageNum * pageSize total; } }3. 迭代器接口分页迭代器/** * 分页迭代器接口按需分页遍历数据 */ public interface PageIteratorT { /** * 判断是否有下一页数据 */ boolean hasNextPage(); /** * 获取下一个元素跨页自动加载 */ T next(); /** * 获取当前页所有元素 */ ListT currentPageData(); /** * 关闭迭代器释放资源 */ void close(); }4. 具体迭代器用户分页迭代器import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * 具体迭代器用户分页迭代器按需加载数据库数据 */ Slf4j Component public class UserPageIterator implements PageIteratorUser { // 依赖数据服务模拟数据库查询 private final UserDataService userDataService; // 分页参数 private final int pageSize; // 当前页数据迭代器 private IteratorUser currentPageIterator; // 当前页码 private int currentPageNum 1; // 总条数首次查询后缓存 private long total -1; // 是否已关闭 private boolean closed false; public UserPageIterator(UserDataService userDataService) { this.userDataService userDataService; this.pageSize 2; // 每页2条可配置 // 加载第一页数据 loadPageData(currentPageNum); } /** * 加载指定页码的数据 */ private void loadPageData(int pageNum) { if (closed) { throw new IllegalStateException(迭代器已关闭); } log.info(加载第{}页数据每页{}条, pageNum, pageSize); PageResultUser pageResult userDataService.queryUserByPage(new PageParam(pageNum, pageSize)); // 缓存总条数 if (total -1) { total pageResult.getTotal(); } // 初始化当前页迭代器 currentPageIterator pageResult.getData().iterator(); currentPageNum pageNum; } /** * 判断是否有下一页数据 */ Override public boolean hasNextPage() { if (closed) { return false; } // 当前页还有元素 → 有下一个 if (currentPageIterator.hasNext()) { return true; } // 当前页无元素判断是否有下一页 PageParam param new PageParam(currentPageNum, pageSize); PageResultUser currentPage userDataService.queryUserByPage(param); return currentPage.hasNext(); } /** * 获取下一个元素跨页自动加载 */ Override public User next() { if (closed) { throw new IllegalStateException(迭代器已关闭); } // 当前页无元素加载下一页 if (!currentPageIterator.hasNext()) { if (!hasNextPage()) { throw new NoSuchElementException(已遍历完所有用户); } loadPageData(currentPageNum 1); } return currentPageIterator.next(); } /** * 获取当前页所有数据 */ Override public ListUser currentPageData() { if (closed) { return new ArrayList(); } PageResultUser currentPage userDataService.queryUserByPage(new PageParam(currentPageNum, pageSize)); return currentPage.getData(); } /** * 关闭迭代器释放资源 */ Override public void close() { log.info(关闭用户分页迭代器); closed true; currentPageIterator null; } }5. 数据服务模拟数据库查询import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * 数据服务模拟数据库分页查询用户 */ Service public class UserDataService { // 模拟数据库中的用户数据 private final ListUser userList new ArrayList(); public UserDataService() { // 初始化10个用户 for (long i 1; i 10; i) { userList.add(new User(i, user i, user i example.com)); } } /** * 分页查询用户 */ public PageResultUser queryUserByPage(PageParam param) { int pageNum param.getPageNum(); int pageSize param.getPageSize(); // 计算起始索引 int start (pageNum - 1) * pageSize; int end Math.min(start pageSize, userList.size()); // 截取当前页数据 ListUser pageData new ArrayList(); if (start userList.size()) { pageData userList.subList(start, end); } // 构建分页结果 PageResultUser result new PageResult(); result.setPageNum(pageNum); result.setPageSize(pageSize); result.setTotal(userList.size()); result.setData(pageData); return result; } }6. 客户端Spring Boot 测试import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; /** * 客户端使用分页迭代器遍历用户数据 */ SpringBootApplication public class SpringIteratorDemoApplication { public static void main(String[] args) { // 1. 启动Spring容器 ConfigurableApplicationContext context SpringApplication.run(SpringIteratorDemoApplication.class, args); UserPageIterator iterator context.getBean(UserPageIterator.class); // 2. 遍历所有用户自动分页加载 System.out.println( 遍历所有用户自动分页 ); int count 0; while (iterator.hasNextPage()) { User user iterator.next(); count; System.out.println(第 count 个用户ID user.getId() 用户名 user.getUsername()); } // 3. 测试获取当前页数据 System.out.println(\n 获取最后一页数据 ); iterator.loadPageData(5); // 跳转到第5页最后一页 iterator.currentPageData().forEach(user - System.out.println(最后一页用户ID user.getId() 用户名 user.getUsername()) ); // 4. 关闭迭代器 iterator.close(); context.close(); } }输出结果 遍历所有用户自动分页 加载第1页数据每页2条 第1个用户ID1用户名user1 第2个用户ID2用户名user2 加载第2页数据每页2条 第3个用户ID3用户名user3 第4个用户ID4用户名user4 加载第3页数据每页2条 第5个用户ID5用户名user5 第6个用户ID6用户名user6 加载第4页数据每页2条 第7个用户ID7用户名user7 第8个用户ID8用户名user8 加载第5页数据每页2条 第9个用户ID9用户名user9 第10个用户ID10用户名user10 获取最后一页数据 加载第5页数据每页2条 最后一页用户ID9用户名user9 最后一页用户ID10用户名user10 关闭用户分页迭代器四、迭代器模式的核心特点与适用场景优点解耦遍历与集合集合只需关注存储遍历交给迭代器符合单一职责原则统一遍历接口不同集合数组、链表、树、数据库分页都可通过相同接口遍历降低使用成本支持多态遍历新增集合类型时只需新增迭代器类无需修改遍历代码开闭原则按需加载数据分页迭代器可避免一次性加载大量数据降低内存占用安全遍历迭代器可控制遍历过程如禁止遍历中修改集合避免并发修改异常。缺点增加代码复杂度简单集合如固定大小数组使用迭代器会增加额外类遍历效率略低迭代器的封装会带来轻微的性能损耗可忽略除非超高频遍历单向遍历为主大部分迭代器是单向的只能往后遍历双向迭代器实现复杂。适用场景遍历集合但不想暴露内部结构如自定义集合类、框架中的容器统一不同集合的遍历方式如同时遍历 ArrayList、LinkedList、HashMap分页遍历大数据如数据库分页查询、接口分批拉取数据、大数据文件读取多线程遍历每个线程持有独立迭代器避免遍历状态冲突需要安全遍历如禁止遍历中修改集合JDK 的 fail-fast 迭代器。五、JDK/ Spring 中的原生应用必须知道迭代器模式是 JDK 中最基础、最常用的设计模式几乎所有集合类都基于它实现1. JDK 核心迭代器java.util.Iterator迭代器核心接口hasNext()、next()、remove()java.util.Collection聚合接口iterator()方法创建迭代器ArrayList.ItrArrayList 的具体迭代器内部类封装数组遍历逻辑HashMap.KeyIterator/ValueIteratorHashMap 的键 / 值迭代器封装哈希表遍历逻辑Iterable接口所有可遍历集合的父接口支持 foreach 循环底层调用iterator()。2. JDK 增强迭代器ListIterator双向迭代器支持向前 / 向后遍历、添加 / 修改元素Spliterator拆分迭代器Java 8 新增支持并行遍历适用于流式计算Enumeration古老的迭代器JDK 1.0已被 Iterator 替代。3. Spring 中的应用org.springframework.util.CollectionUtils提供统一的迭代器工具方法Spring Data JPA分页迭代Pageable/Page结合迭代器实现分页遍历Spring Batch数据读取ItemReader基于迭代器模式实现分批读取数据ApplicationContext遍历 BeangetBeansOfType()返回的集合可通过迭代器遍历。六、迭代器模式 vs 访问者模式易混淆点维度迭代器模式访问者模式核心目的遍历集合中的元素不修改元素操作集合中的元素修改 / 处理元素核心结构迭代器接口 聚合接口访问者接口 元素接口关注点遍历的 “方式”如何遍历元素的 “操作”对元素做什么典型场景遍历集合、分页查询、数据读取元素操作、数据导出、规则校验总结迭代器模式的核心是将集合的遍历逻辑抽离为独立的迭代器对象实现遍历与存储的解耦核心角色包括迭代器接口统一遍历方法、具体迭代器封装遍历逻辑、聚合接口创建迭代器、具体聚合存储元素业务开发中迭代器模式最实用的场景是分页遍历大数据集合如数据库分页、分批接口调用可避免一次性加载大量数据JDK 中所有集合类都基于迭代器模式实现Iterator接口是遍历所有集合的标准方式foreach 循环底层也是调用迭代器。