Java 迭代器模式 3 大实战场景:从 JDBC ResultSet 到自定义集合遍历

在 Java 开发中,我们经常需要处理各种集合数据的遍历操作。迭代器模式(Iterator Pattern)作为一种行为型设计模式,提供了一种统一的方式来访问集合对象中的元素,而无需暴露其内部表示。本文将深入探讨迭代器模式在 Java 生态中的三个高级应用场景,帮助开发者更好地理解这一模式的实际价值。

1. JDBC ResultSet 的迭代器模式实现

JDBC(Java Database Connectivity)是 Java 连接数据库的标准 API,而 ResultSet 则是查询结果集的载体。ResultSet 本质上就是一个迭代器模式的经典实现。

1.1 ResultSet 的迭代器特性

ResultSet 提供了类似迭代器的接口来遍历查询结果:

try (Connection conn = DriverManager.getConnection(url, user, password);
     Statement stmt = conn.createStatement();
     ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
    
    while (rs.next()) {  // 相当于 hasNext()
        int id = rs.getInt("id");  // 相当于 next()
        String name = rs.getString("name");
        // 处理数据...
    }
}

关键点分析

  • next() 方法:将游标移动到下一行,并返回是否有更多数据
  • 各种 getXxx() 方法:获取当前行的列数据
  • 内部状态管理:ResultSet 维护了当前行的位置信息

1.2 自定义 ResultSet 包装器

我们可以进一步封装 ResultSet,使其更符合迭代器模式的标准接口:

public class ResultSetIterator<T> implements Iterator<T> {
    private final ResultSet rs;
    private final Function<ResultSet, T> mapper;
    private boolean hasNext;

    public ResultSetIterator(ResultSet rs, Function<ResultSet, T> mapper) {
        this.rs = rs;
        this.mapper = mapper;
        try {
            this.hasNext = rs.next();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean hasNext() {
        return hasNext;
    }

    @Override
    public T next() {
        if (!hasNext) throw new NoSuchElementException();
        try {
            T value = mapper.apply(rs);
            hasNext = rs.next();
            return value;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

使用示例:

ResultSetIterator<User> iterator = new ResultSetIterator<>(rs, rs -> 
    new User(rs.getInt("id"), rs.getString("name")));

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

2. Java 8 Stream API 与 Spliterator

Java 8 引入的 Stream API 为集合操作提供了函数式编程能力,而其底层依赖于 Spliterator(可分割迭代器)这一增强版迭代器。

2.1 Spliterator 核心方法

Spliterator 接口定义了以下关键方法:

方法 描述
boolean tryAdvance(Consumer<? super T> action) 尝试处理下一个元素
Spliterator<T> trySplit() 尝试分割迭代器以支持并行处理
long estimateSize() 估算剩余元素数量
int characteristics() 返回迭代器特性标志

2.2 自定义集合的 Spliterator 实现

假设我们有一个自定义的二叉树结构,可以为其实现 Spliterator:

public class BinaryTree<T> {
    private Node<T> root;
    
    private static class Node<T> {
        T value;
        Node<T> left, right;
    }

    public Spliterator<T> spliterator() {
        return new BinaryTreeSpliterator<>(root);
    }

    private static class BinaryTreeSpliterator<T> implements Spliterator<T> {
        private final Deque<Node<T>> stack = new ArrayDeque<>();

        public BinaryTreeSpliterator(Node<T> root) {
            if (root != null) stack.push(root);
        }

        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
            if (stack.isEmpty()) return false;
            
            Node<T> current = stack.pop();
            action.accept(current.value);
            
            if (current.right != null) stack.push(current.right);
            if (current.left != null) stack.push(current.left);
            
            return true;
        }

        @Override
        public Spliterator<T> trySplit() {
            // 简化实现,实际中可以实现更复杂的分割逻辑
            return null;
        }

        @Override
        public long estimateSize() {
            return Long.MAX_VALUE; // 未知大小
        }

        @Override
        public int characteristics() {
            return Spliterator.ORDERED | Spliterator.NONNULL;
        }
    }
}

使用示例:

BinaryTree<String> tree = new BinaryTree<>();
// 填充树结构...

tree.spliterator().forEachRemaining(System.out::println);

3. 自定义数据结构的迭代器实现

对于复杂的数据结构(如图、树等),标准集合接口可能无法满足需求,这时需要自定义迭代器。

3.1 二叉树的前序和中序迭代器

下面展示如何为二叉树实现两种不同的遍历方式:

public class BinaryTree<T> implements Iterable<T> {
    private Node<T> root;
    
    public Iterator<T> preOrderIterator() {
        return new PreOrderIterator();
    }
    
    public Iterator<T> inOrderIterator() {
        return new InOrderIterator();
    }

    // 前序遍历迭代器
    private class PreOrderIterator implements Iterator<T> {
        private final Deque<Node<T>> stack = new ArrayDeque<>();
        
        public PreOrderIterator() {
            if (root != null) stack.push(root);
        }
        
        @Override
        public boolean hasNext() {
            return !stack.isEmpty();
        }
        
        @Override
        public T next() {
            Node<T> current = stack.pop();
            if (current.right != null) stack.push(current.right);
            if (current.left != null) stack.push(current.left);
            return current.value;
        }
    }

    // 中序遍历迭代器
    private class InOrderIterator implements Iterator<T> {
        private final Deque<Node<T>> stack = new ArrayDeque<>();
        private Node<T> current;
        
        public InOrderIterator() {
            current = root;
            pushLeft(current);
        }
        
        private void pushLeft(Node<T> node) {
            while (node != null) {
                stack.push(node);
                node = node.left;
            }
        }
        
        @Override
        public boolean hasNext() {
            return !stack.isEmpty();
        }
        
        @Override
        public T next() {
            Node<T> node = stack.pop();
            pushLeft(node.right);
            return node.value;
        }
    }
}

3.2 图结构的迭代器实现

对于图结构,我们可以实现广度优先搜索(BFS)和深度优先搜索(DFS)迭代器:

public class Graph<T> implements Iterable<T> {
    private final Map<T, List<T>> adjacencyList = new HashMap<>();
    
    public void addEdge(T source, T destination) {
        adjacencyList.computeIfAbsent(source, k -> new ArrayList<>()).add(destination);
    }
    
    public Iterator<T> bfsIterator(T start) {
        return new BfsIterator(start);
    }
    
    public Iterator<T> dfsIterator(T start) {
        return new DfsIterator(start);
    }
    
    private class BfsIterator implements Iterator<T> {
        private final Queue<T> queue = new LinkedList<>();
        private final Set<T> visited = new HashSet<>();
        
        public BfsIterator(T start) {
            queue.add(start);
            visited.add(start);
        }
        
        @Override
        public boolean hasNext() {
            return !queue.isEmpty();
        }
        
        @Override
        public T next() {
            T current = queue.remove();
            for (T neighbor : adjacencyList.getOrDefault(current, Collections.emptyList())) {
                if (!visited.contains(neighbor)) {
                    visited.add(neighbor);
                    queue.add(neighbor);
                }
            }
            return current;
        }
    }
    
    private class DfsIterator implements Iterator<T> {
        private final Deque<T> stack = new ArrayDeque<>();
        private final Set<T> visited = new HashSet<>();
        
        public DfsIterator(T start) {
            stack.push(start);
            visited.add(start);
        }
        
        @Override
        public boolean hasNext() {
            return !stack.isEmpty();
        }
        
        @Override
        public T next() {
            T current = stack.pop();
            for (T neighbor : adjacencyList.getOrDefault(current, Collections.emptyList())) {
                if (!visited.contains(neighbor)) {
                    visited.add(neighbor);
                    stack.push(neighbor);
                }
            }
            return current;
        }
    }
}

4. 迭代器模式的高级应用技巧

4.1 过滤迭代器

我们可以创建装饰器模式的过滤迭代器,只返回满足特定条件的元素:

public class FilteringIterator<T> implements Iterator<T> {
    private final Iterator<T> source;
    private final Predicate<T> predicate;
    private T nextElement;
    private boolean hasNext;
    
    public FilteringIterator(Iterator<T> source, Predicate<T> predicate) {
        this.source = source;
        this.predicate = predicate;
        advance();
    }
    
    private void advance() {
        hasNext = false;
        while (source.hasNext()) {
            nextElement = source.next();
            if (predicate.test(nextElement)) {
                hasNext = true;
                break;
            }
        }
    }
    
    @Override
    public boolean hasNext() {
        return hasNext;
    }
    
    @Override
    public T next() {
        if (!hasNext) throw new NoSuchElementException();
        T result = nextElement;
        advance();
        return result;
    }
}

使用示例:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Iterator<Integer> evenNumbers = new FilteringIterator<>(
    numbers.iterator(), 
    n -> n % 2 == 0
);

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

4.2 线程安全迭代器

在多线程环境中,我们需要确保迭代器的线程安全性:

public class SynchronizedIterator<T> implements Iterator<T> {
    private final Iterator<T> source;
    private final Object lock;
    
    public SynchronizedIterator(Iterator<T> source, Object lock) {
        this.source = source;
        this.lock = lock != null ? lock : this;
    }
    
    @Override
    public boolean hasNext() {
        synchronized (lock) {
            return source.hasNext();
        }
    }
    
    @Override
    public T next() {
        synchronized (lock) {
            return source.next();
        }
    }
    
    @Override
    public void remove() {
        synchronized (lock) {
            source.remove();
        }
    }
}

4.3 组合迭代器

对于嵌套集合结构,我们可以创建组合迭代器来扁平化遍历:

public class CompositeIterator<T> implements Iterator<T> {
    private final Iterator<? extends Iterable<T>> outerIterator;
    private Iterator<T> currentInnerIterator;
    
    public CompositeIterator(Iterable<? extends Iterable<T>> outerIterable) {
        this.outerIterator = outerIterable.iterator();
        this.currentInnerIterator = Collections.emptyIterator();
    }
    
    @Override
    public boolean hasNext() {
        while (!currentInnerIterator.hasNext()) {
            if (!outerIterator.hasNext()) return false;
            currentInnerIterator = outerIterator.next().iterator();
        }
        return true;
    }
    
    @Override
    public T next() {
        if (!hasNext()) throw new NoSuchElementException();
        return currentInnerIterator.next();
    }
}

使用示例:

List<List<String>> nestedList = Arrays.asList(
    Arrays.asList("A", "B", "C"),
    Arrays.asList("D", "E"),
    Collections.emptyList(),
    Arrays.asList("F", "G", "H")
);

Iterator<String> compositeIt = new CompositeIterator<>(nestedList);
while (compositeIt.hasNext()) {
    System.out.println(compositeIt.next());
}

在实际项目中,迭代器模式的应用远比这些基础示例复杂。理解其核心思想并灵活运用,可以显著提升代码的可维护性和扩展性。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐