Deepeek用大白话讲解 --> 迭代器模式(企业级场景1,多种遍历方式2,隐藏集合结构3,Java集合框架4)

迭代器模式大白话讲解

一句话概括

就像DVD遥控器:你不用知道电影是怎么存储在光盘上的,按下一曲就能看到下一段内容


现实生活比喻

场景1:DVD播放器

  • DVD光盘:存储了整部电影(聚合对象)
  • 遥控器:迭代器
  • :客户端
  • 过程:你按"下一曲"按钮,不用关心光盘怎么存储,就能看到下一段

场景2:书架上的书

  • 书架:书集合(聚合对象)
  • 你的手指:迭代器
  • :客户端
  • 过程:你用手指一本本划过书架,不用关心书架的结构,就能遍历所有书

完整代码示例

场景1:电视频道迭代器

java 复制代码
/**
 * 迭代器模式 - 电视频道管理
 */
public class Main {
    public static void main(String[] args) {
        System.out.println("=== 电视频道管理系统 ===");
        
        // 创建电视频道集合
        ChannelCollection channels = new ChannelCollectionImpl();
        
        // 添加一些频道
        channels.addChannel(new Channel(1, "CCTV-1", "综合频道"));
        channels.addChannel(new Channel(2, "CCTV-2", "财经频道"));
        channels.addChannel(new Channel(3, "CCTV-5", "体育频道"));
        channels.addChannel(new Channel(4, "湖南卫视", "娱乐频道"));
        channels.addChannel(new Channel(5, "浙江卫视", "娱乐频道"));
        channels.addChannel(new Channel(6, "CCTV-13", "新闻频道"));
        channels.addChannel(new Channel(7, "凤凰卫视", "新闻频道"));
        channels.addChannel(new Channel(8, "Discovery", "纪录片频道"));
        
        // 普通遍历所有频道
        System.out.println("\n--- 所有电视频道 ---");
        ChannelIterator iterator = channels.createIterator();
        while (iterator.hasNext()) {
            Channel channel = iterator.next();
            System.out.println(channel);
        }
        
        // 按类型遍历
        System.out.println("\n--- 娱乐频道 ---");
        ChannelIterator entertainmentIterator = channels.createIteratorByType("娱乐频道");
        while (entertainmentIterator.hasNext()) {
            Channel channel = entertainmentIterator.next();
            System.out.println(channel);
        }
        
        System.out.println("\n--- 新闻频道 ---");
        ChannelIterator newsIterator = channels.createIteratorByType("新闻频道");
        while (newsIterator.hasNext()) {
            Channel channel = newsIterator.next();
            System.out.println(channel);
        }
        
        // 反向遍历
        System.out.println("\n--- 反向遍历所有频道 ---");
        ChannelIterator reverseIterator = channels.createReverseIterator();
        while (reverseIterator.hasNext()) {
            Channel channel = reverseIterator.next();
            System.out.println(channel);
        }
    }
}

/**
 * 电视频道类
 */
class Channel {
    private int number;
    private String name;
    private String type;
    
    public Channel(int number, String name, String type) {
        this.number = number;
        this.name = name;
        this.type = type;
    }
    
    public int getNumber() { return number; }
    public String getName() { return name; }
    public String getType() { return type; }
    
    @Override
    public String toString() {
        return "频道" + number + ": " + name + " (" + type + ")";
    }
}

/**
 * 迭代器接口
 */
interface ChannelIterator {
    boolean hasNext();
    Channel next();
    void reset();
}

/**
 * 具体迭代器 - 普通迭代器
 */
class ChannelIteratorImpl implements ChannelIterator {
    private List<Channel> channels;
    private int position;
    
    public ChannelIteratorImpl(List<Channel> channels) {
        this.channels = channels;
        this.position = 0;
    }
    
    @Override
    public boolean hasNext() {
        return position < channels.size();
    }
    
    @Override
    public Channel next() {
        if (!hasNext()) {
            throw new NoSuchElementException("没有更多频道了");
        }
        Channel channel = channels.get(position);
        position++;
        return channel;
    }
    
    @Override
    public void reset() {
        position = 0;
    }
}

/**
 * 具体迭代器 - 按类型过滤的迭代器
 */
class ChannelTypeIterator implements ChannelIterator {
    private List<Channel> channels;
    private String type;
    private int position;
    
    public ChannelTypeIterator(List<Channel> channels, String type) {
        this.channels = channels;
        this.type = type;
        this.position = 0;
    }
    
    @Override
    public boolean hasNext() {
        // 找到下一个符合类型的频道
        while (position < channels.size()) {
            if (channels.get(position).getType().equals(type)) {
                return true;
            }
            position++;
        }
        return false;
    }
    
    @Override
    public Channel next() {
        if (!hasNext()) {
            throw new NoSuchElementException("没有更多" + type + "频道了");
        }
        Channel channel = channels.get(position);
        position++;
        return channel;
    }
    
    @Override
    public void reset() {
        position = 0;
    }
}

/**
 * 具体迭代器 - 反向迭代器
 */
class ReverseChannelIterator implements ChannelIterator {
    private List<Channel> channels;
    private int position;
    
    public ReverseChannelIterator(List<Channel> channels) {
        this.channels = channels;
        this.position = channels.size() - 1; // 从最后开始
    }
    
    @Override
    public boolean hasNext() {
        return position >= 0;
    }
    
    @Override
    public Channel next() {
        if (!hasNext()) {
            throw new NoSuchElementException("没有更多频道了");
        }
        Channel channel = channels.get(position);
        position--;
        return channel;
    }
    
    @Override
    public void reset() {
        position = channels.size() - 1;
    }
}

/**
 * 聚合接口 - 频道集合
 */
interface ChannelCollection {
    void addChannel(Channel channel);
    void removeChannel(Channel channel);
    ChannelIterator createIterator();
    ChannelIterator createIteratorByType(String type);
    ChannelIterator createReverseIterator();
}

/**
 * 具体聚合 - 频道集合实现
 */
class ChannelCollectionImpl implements ChannelCollection {
    private List<Channel> channels = new ArrayList<>();
    
    @Override
    public void addChannel(Channel channel) {
        channels.add(channel);
    }
    
    @Override
    public void removeChannel(Channel channel) {
        channels.remove(channel);
    }
    
    @Override
    public ChannelIterator createIterator() {
        return new ChannelIteratorImpl(channels);
    }
    
    @Override
    public ChannelIterator createIteratorByType(String type) {
        return new ChannelTypeIterator(channels, type);
    }
    
    @Override
    public ChannelIterator createReverseIterator() {
        return new ReverseChannelIterator(channels);
    }
}

运行结果

复制代码
=== 电视频道管理系统 ===

--- 所有电视频道 ---
频道1: CCTV-1 (综合频道)
频道2: CCTV-2 (财经频道)
频道3: CCTV-5 (体育频道)
频道4: 湖南卫视 (娱乐频道)
频道5: 浙江卫视 (娱乐频道)
频道6: CCTV-13 (新闻频道)
频道7: 凤凰卫视 (新闻频道)
频道8: Discovery (纪录片频道)

--- 娱乐频道 ---
频道4: 湖南卫视 (娱乐频道)
频道5: 浙江卫视 (娱乐频道)

--- 新闻频道 ---
频道6: CCTV-13 (新闻频道)
频道7: 凤凰卫视 (新闻频道)

--- 反向遍历所有频道 ---
频道8: Discovery (纪录片频道)
频道7: 凤凰卫视 (新闻频道)
频道6: CCTV-13 (新闻频道)
频道5: 浙江卫视 (娱乐频道)
频道4: 湖南卫视 (娱乐频道)
频道3: CCTV-5 (体育频道)
频道2: CCTV-2 (财经频道)
频道1: CCTV-1 (综合频道)

场景2:文件系统遍历器

java 复制代码
/**
 * 迭代器模式 - 文件系统遍历
 */
public class FileSystemExample {
    public static void main(String[] args) {
        System.out.println("=== 文件系统遍历 ===");
        
        // 构建一个文件系统树
        FileSystemItem root = new Directory("root");
        
        Directory docs = new Directory("文档");
        docs.addItem(new File("简历.doc", 200));
        docs.addItem(new File("报告.pdf", 500));
        
        Directory photos = new Directory("照片");
        photos.addItem(new File("毕业照.jpg", 1500));
        photos.addItem(new File("旅游照.jpg", 1200));
        
        Directory music = new Directory("音乐");
        music.addItem(new File("歌曲1.mp3", 8000));
        music.addItem(new File("歌曲2.mp3", 7500));
        
        root.addItem(docs);
        root.addItem(photos);
        root.addItem(music);
        
        // 创建不同的迭代器
        System.out.println("\n--- 深度优先遍历 ---");
        FileSystemIterator dfsIterator = root.createDepthFirstIterator();
        while (dfsIterator.hasNext()) {
            FileSystemItem item = dfsIterator.next();
            System.out.println(item);
        }
        
        System.out.println("\n--- 只遍历文件(过滤文件夹) ---");
        FileSystemIterator fileOnlyIterator = root.createFileOnlyIterator();
        while (fileOnlyIterator.hasNext()) {
            FileSystemItem item = fileOnlyIterator.next();
            System.out.println(item);
        }
        
        System.out.println("\n--- 按大小过滤(大于1MB的文件) ---");
        FileSystemIterator largeFileIterator = root.createLargeFileIterator(1000);
        while (largeFileIterator.hasNext()) {
            FileSystemItem item = largeFileIterator.next();
            System.out.println(item);
        }
        
        // 计算总大小
        System.out.println("\n=== 文件统计 ===");
        int totalSize = 0;
        FileSystemIterator sizeIterator = root.createFileOnlyIterator();
        while (sizeIterator.hasNext()) {
            FileSystemItem item = sizeIterator.next();
            totalSize += ((File) item).getSize();
        }
        System.out.println("所有文件总大小: " + totalSize + "KB");
    }
}

/**
 * 文件系统项接口
 */
interface FileSystemItem {
    String getName();
    FileSystemIterator createDepthFirstIterator();
    FileSystemIterator createFileOnlyIterator();
    FileSystemIterator createLargeFileIterator(int minSizeKB);
}

/**
 * 文件类
 */
class File implements FileSystemItem {
    private String name;
    private int size; // KB
    
    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }
    
    @Override
    public String getName() {
        return name;
    }
    
    public int getSize() {
        return size;
    }
    
    @Override
    public FileSystemIterator createDepthFirstIterator() {
        return new SingleItemIterator(this);
    }
    
    @Override
    public FileSystemIterator createFileOnlyIterator() {
        return new SingleItemIterator(this);
    }
    
    @Override
    public FileSystemIterator createLargeFileIterator(int minSizeKB) {
        if (size >= minSizeKB) {
            return new SingleItemIterator(this);
        }
        return new EmptyIterator();
    }
    
    @Override
    public String toString() {
        return "文件: " + name + " (" + size + "KB)";
    }
}

/**
 * 目录类
 */
class Directory implements FileSystemItem {
    private String name;
    private List<FileSystemItem> items = new ArrayList<>();
    
    public Directory(String name) {
        this.name = name;
    }
    
    public void addItem(FileSystemItem item) {
        items.add(item);
    }
    
    @Override
    public String getName() {
        return name;
    }
    
    @Override
    public FileSystemIterator createDepthFirstIterator() {
        return new DepthFirstIterator(this);
    }
    
    @Override
    public FileSystemIterator createFileOnlyIterator() {
        return new FileOnlyIterator(this);
    }
    
    @Override
    public FileSystemIterator createLargeFileIterator(int minSizeKB) {
        return new LargeFileIterator(this, minSizeKB);
    }
    
    public List<FileSystemItem> getItems() {
        return items;
    }
    
    @Override
    public String toString() {
        return "目录: [" + name + "]";
    }
}

/**
 * 文件系统迭代器接口
 */
interface FileSystemIterator {
    boolean hasNext();
    FileSystemItem next();
}

/**
 * 具体迭代器 - 深度优先迭代器
 */
class DepthFirstIterator implements FileSystemIterator {
    private Stack<FileSystemItem> stack = new Stack<>();
    
    public DepthFirstIterator(FileSystemItem root) {
        stack.push(root);
    }
    
    @Override
    public boolean hasNext() {
        return !stack.isEmpty();
    }
    
    @Override
    public FileSystemItem next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        
        FileSystemItem current = stack.pop();
        
        // 如果是目录,将其子项逆序压入栈中(保证正序遍历)
        if (current instanceof Directory) {
            List<FileSystemItem> items = ((Directory) current).getItems();
            for (int i = items.size() - 1; i >= 0; i--) {
                stack.push(items.get(i));
            }
        }
        
        return current;
    }
}

/**
 * 具体迭代器 - 只遍历文件的迭代器
 */
class FileOnlyIterator implements FileSystemIterator {
    private Stack<FileSystemItem> stack = new Stack<>();
    
    public FileOnlyIterator(FileSystemItem root) {
        stack.push(root);
    }
    
    @Override
    public boolean hasNext() {
        // 跳过目录,只找文件
        while (!stack.isEmpty() && stack.peek() instanceof Directory) {
            FileSystemItem current = stack.pop();
            List<FileSystemItem> items = ((Directory) current).getItems();
            for (int i = items.size() - 1; i >= 0; i--) {
                stack.push(items.get(i));
            }
        }
        return !stack.isEmpty();
    }
    
    @Override
    public FileSystemItem next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        return stack.pop();
    }
}

/**
 * 具体迭代器 - 大文件迭代器
 */
class LargeFileIterator implements FileSystemIterator {
    private Stack<FileSystemItem> stack = new Stack<>();
    private int minSizeKB;
    private FileSystemItem nextFile;
    
    public LargeFileIterator(FileSystemItem root, int minSizeKB) {
        this.minSizeKB = minSizeKB;
        stack.push(root);
        findNext();
    }
    
    private void findNext() {
        nextFile = null;
        while (!stack.isEmpty() && nextFile == null) {
            FileSystemItem current = stack.pop();
            
            if (current instanceof File) {
                if (((File) current).getSize() >= minSizeKB) {
                    nextFile = current;
                }
            } else if (current instanceof Directory) {
                List<FileSystemItem> items = ((Directory) current).getItems();
                for (int i = items.size() - 1; i >= 0; i--) {
                    stack.push(items.get(i));
                }
            }
        }
    }
    
    @Override
    public boolean hasNext() {
        return nextFile != null;
    }
    
    @Override
    public FileSystemItem next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        FileSystemItem result = nextFile;
        findNext();
        return result;
    }
}

/**
 * 单项目迭代器(用于文件)
 */
class SingleItemIterator implements FileSystemIterator {
    private FileSystemItem item;
    private boolean consumed = false;
    
    public SingleItemIterator(FileSystemItem item) {
        this.item = item;
    }
    
    @Override
    public boolean hasNext() {
        return !consumed;
    }
    
    @Override
    public FileSystemItem next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        consumed = true;
        return item;
    }
}

/**
 * 空迭代器
 */
class EmptyIterator implements FileSystemIterator {
    @Override
    public boolean hasNext() {
        return false;
    }
    
    @Override
    public FileSystemItem next() {
        throw new NoSuchElementException();
    }
}

运行结果

复制代码
=== 文件系统遍历 ===

--- 深度优先遍历 ---
目录: [root]
目录: [音乐]
文件: 歌曲2.mp3 (7500KB)
文件: 歌曲1.mp3 (8000KB)
目录: [照片]
文件: 旅游照.jpg (1200KB)
文件: 毕业照.jpg (1500KB)
目录: [文档]
文件: 报告.pdf (500KB)
文件: 简历.doc (200KB)

--- 只遍历文件(过滤文件夹) ---
文件: 歌曲2.mp3 (7500KB)
文件: 歌曲1.mp3 (8000KB)
文件: 旅游照.jpg (1200KB)
文件: 毕业照.jpg (1500KB)
文件: 报告.pdf (500KB)
文件: 简历.doc (200KB)

--- 按大小过滤(大于1MB的文件) ---
文件: 歌曲2.mp3 (7500KB)
文件: 歌曲1.mp3 (8000KB)
文件: 旅游照.jpg (1200KB)
文件: 毕业照.jpg (1500KB)

=== 文件统计 ===
所有文件总大小: 18900KB

迭代器模式的核心结构

复制代码
    Aggregate(聚合接口)
        ↑
ConcreteAggregate(具体聚合) → createIterator()
        ↓ 返回
    Iterator(迭代器接口)
        ↑
ConcreteIterator(具体迭代器) → 遍历内部集合

关键特征:

  • 封装遍历:将遍历逻辑从集合中分离出来
  • 统一接口:不同的集合提供相同的遍历接口
  • 多种遍历方式:可以同时进行多个遍历
  • 隐藏实现:客户端不知道集合的内部结构

Java中的迭代器

Java集合框架中的迭代器

java 复制代码
// Java的Collection接口都实现了Iterable
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");

// 使用迭代器
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    System.out.println(item);
}

// 增强for循环(底层使用迭代器)
for (String item : list) {
    System.out.println(item);
}

自定义可迭代对象

java 复制代码
class MyCollection implements Iterable<String> {
    private String[] items = {"A", "B", "C"};
    
    @Override
    public Iterator<String> iterator() {
        return new Iterator<String>() {
            private int index = 0;
            
            @Override
            public boolean hasNext() {
                return index < items.length;
            }
            
            @Override
            public String next() {
                return items[index++];
            }
        };
    }
}

迭代器模式的几种类型

1. 外部迭代器(客户端控制迭代)

java 复制代码
// 客户端显式调用next()和hasNext()
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
    Object item = iterator.next();
    // 处理item
}

2. 内部迭代器(迭代器控制迭代)

java 复制代码
// 客户端提供处理函数,迭代器控制循环
collection.forEach(item -> {
    // 处理item
});

3. 游标迭代器(C++风格)

java 复制代码
// 使用begin()和end()方法
for (Iterator it = collection.begin(); it != collection.end(); it++) {
    Object item = it.get();
}

适用场景(大白话版)

适合用迭代器模式的场景:

  1. 需要多种遍历方式

    java 复制代码
    // 正序遍历、逆序遍历、按条件过滤遍历
    // 树结构的深度优先、广度优先遍历
  2. 需要统一遍历接口

    java 复制代码
    // 不同类型的集合(数组、链表、树)提供相同的遍历方式
    // 客户端代码不需要知道集合的具体类型
  3. 隐藏集合内部结构

    java 复制代码
    // 集合的内部实现可能改变,但迭代接口不变
    // 今天用数组,明天可能改成链表,客户端代码不用改

不适合的场景:

  1. 简单集合:如果集合非常简单,直接遍历即可
  2. 只需要一种遍历方式:如果只有一种遍历需求
  3. 性能敏感:迭代器调用有额外开销

优缺点

优点:

  • 简化客户端代码:客户端只需要调用统一接口
  • 支持多种遍历:可以为同一集合提供不同遍历方式
  • 封装集合内部:集合的内部结构变化不影响客户端
  • 开闭原则:新增迭代器不影响现有代码

缺点:

  • 增加复杂度:对于简单集合显得过度设计
  • 性能开销:迭代器调用比直接访问稍慢
  • 遍历状态:并发修改可能导致问题

与foreach循环的关系

java 复制代码
// Java的foreach循环就是迭代器模式的语法糖
List<String> list = Arrays.asList("A", "B", "C");

// 写法1:foreach循环(简洁)
for (String item : list) {
    System.out.println(item);
}

// 写法2:显式迭代器(灵活)
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    System.out.println(item);
    
    // 迭代器可以做更多事情
    if (item.equals("B")) {
        iterator.remove(); // 删除当前元素
    }
}

实际应用案例

1. Java集合框架

java 复制代码
// List、Set、Map等都支持迭代器
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
Map<String, Integer> map = new HashMap<>();

// 都有统一的迭代方式
for (String item : list) { ... }
for (String item : set) { ... }
for (Map.Entry<String, Integer> entry : map.entrySet()) { ... }

2. 数据库结果集

java 复制代码
// JDBC的ResultSet就是迭代器模式
ResultSet rs = statement.executeQuery("SELECT * FROM users");
while (rs.next()) {  // hasNext()
    String name = rs.getString("name");  // next()
    int age = rs.getInt("age");
}

3. 文件读取

java 复制代码
// 按行读取文件
BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
String line;
while ((line = reader.readLine()) != null) {  // hasNext()和next()的结合
    System.out.println(line);
}
reader.close();

4. 流处理

java 复制代码
// Java 8的Stream API是增强的迭代器
list.stream()
    .filter(s -> s.startsWith("A"))
    .map(String::toUpperCase)
    .forEach(System.out::println);

总结

迭代器模式就是:

  • 遥控器:控制播放进度,不用知道光盘结构
  • 导游:带你游览景点,不用自己找路
  • 取票机:一张张出票,不用知道票库结构
  • 翻书:一页页翻看,不用知道书怎么装订

核心口诀:

集合遍历太麻烦,

各种结构不一般。

迭代模式来统一,

隐藏细节真简单!

就像现实中的:

  • 📺 电视遥控器:换台不看电路板
  • 📚 图书馆索书号:按号找书不看书架结构
  • 🎵 音乐播放列表:下一首不看文件存储
  • 🗺️ 地图导航:路线规划不看地图数据存储

记住:当你需要遍历一个集合,但又不想暴露它的内部结构时,考虑使用迭代器模式!

相关推荐
SmoothSailingT2 小时前
C#——LINQ方法
开发语言·c#·linq
景川呀2 小时前
Java的类加载器
java·开发语言·java类加载器
yaoxin5211232 小时前
274. Java Stream API - 过滤操作(filter):筛选你想要的数据
java·windows
小白勇闯网安圈2 小时前
Java面向对象(上)
java
k***92162 小时前
Python 科学计算有哪些提高运算速度的技巧
开发语言·python
superman超哥2 小时前
仓颉条件变量深度解析与实践:解锁高效并发同步
开发语言·python·c#·仓颉
一点晖光2 小时前
maven推送项目到harhor私有仓库
java·maven
代码or搬砖2 小时前
MySQL窗口函数 OVER()讲解
java·mysql
道法自然|~3 小时前
【PHP】简单的脚本/扫描器拦截与重要文件保护
开发语言·爬虫·php