关于Iterable接口和 Iteraotor接口的关系和实现

本文深入探讨了迭代器和过滤器的概念及其在数据结构中的应用,包括如何通过迭代器进行数据遍历,以及如何使用过滤器实现条件筛选。详细介绍了迭代器的实现方式和条件过滤迭代器的实现,同时展示了支持peek功能的迭代器的使用场景。通过实例代码解释了BST迭代器和过滤迭代器的工作原理。

Iterable是说这个对象支持iterate操作,是可iterate的,需要遍历的话,给你返回一个iterator进行遍历

Iterator对应具体的一次遍历,核心数据是遍历指针


Iterator 封装了目标被遍历对象,并维护遍历状态,(可能不只是简单的遍历指针,因为被遍历对象不一定是线性结构,比如树,遍历状态是stack的状态和当前节点root)

其他辅助状态:

flag: 标志当前是否有item 取出来了还未被取走

current: 存放下一个item


boolean hasNext()


如果flag 为true, 则直接返回true, 

否则尝试取下一个item, 如果取到了,放到current里,设置flag为true,如果流结束了都没有item了,flag一直会为false, 最后返回flag。


Item next()

要先看flag, flag为真才返回item,


注意:1)flag 和current可以合而为一, flag用 current是否为null代表,2)必须hasNext(), 之后next()结合使用。


根据需求不同,有2种实现方式

1)预先准备好下一个数据current,一般是在hasNext()里准备,next()只是返回current并置current为null

2)不预先准备,没有current变量。hasNext()判断是否还有数据,next真正往前走返回数据,如BSTIterator


class BSTIterator {
public:
    BSTIterator(TreeNode *root) {
        this->root = root;
    }

    /** @return whether we have a next smallest number */
    bool hasNext() {
        return root || !s.empty();
    }

    /** @return the next smallest number */
    int next() {
        while (root || !s.empty()) {
            if (root) {
                s.push(root);
                root = root->left;
            } else {
                root = s.top(); s.pop();
                int ret = root->val;
                root = root->right;
                return ret;
            }
        }
    }
private:
    TreeNode *root;
    stack<TreeNode*> s;
};

条件过滤Iterator

标准的预先准备current的方式:因为要判断是否符合条件

class FilterIterator<T> implements Iterator<T> {
	private Iterator<T> it;
	private T current;
	private Predicate<T> filter;
	public FilterIterator (Iterator<T> sourceIterator, Predicate<T> predicate){
		it = sourceIterator;
		current = null;
		filter = predicate;
	}
	@Override
	public boolean hasNext() {
		if (current != null) return true;
		while (it.hasNext()) {
			T temp = it.next();
			if (filter.test(temp)) {
				current = temp;
				return true;
			}
		}
		return false;
	}
	@Override
	public T next() {
		T ret = current;
		current = null;
		return ret;
	}
}



支持peek的 Iterator

两种方式结合

class PeekingIterator implements Iterator<Integer> {
    private Iterator<Integer> it;
    Integer current;
	public PeekingIterator(Iterator<Integer> iterator) {
	    // initialize any member here.
	    this.it = iterator;
	    current = null;
	}

    // Returns the next element in the iteration without advancing the iterator.
	public Integer peek() {
        if (null != current) return current;
        current = it.next();
        return current;
	}

	// hasNext() and next() should behave the same as in the Iterator interface.
	// Override them if needed.
	@Override
	public Integer next() {
	    if (null != current) {
	        Integer ret = current;
	        current = null;
	        return ret;
	    }
	    else {
	        return it.next();
	    }
	}

	@Override
	public boolean hasNext() {
	    return current != null || it.hasNext();
	}
}









`Iterable` 是 Java 中一个非常重要的接口,位于 `java.lang` 包中。它定义了一个对象是否可以被迭代(例如用于增强 for 循环,即 `for-each` 循环)。任何实现了 `Iterable<T>` 接口的类都可以在 `for-each` 循环中使用。 --- ### 如何创建并使用 `Iterable` 接口实现 `Iterable` 接口,你的类必须实现 `iterator()` 方法,该方法返回一个 `Iterator<T>` 对象,用于遍历集合中的元素。 #### 示例:创建一个自定义的可迭代类 ```java import java.util.*; // 自定义一个容器类,存储整数并支持迭代 class MyNumberList implements Iterable<Integer> { private List<Integer> numbers; public MyNumberList() { this.numbers = new ArrayList<>(); } public void add(int number) { numbers.add(number); } // 实现 Iterable 接口的核心方法 @Override public Iterator<Integer> iterator() { return numbers.iterator(); // 直接委托给 ArrayList 的迭代器 } } // 使用示例 public class IterableExample { public static void main(String[] args) { MyNumberList list = new MyNumberList(); list.add(10); list.add(20); list.add(30); // 使用增强 for 循环(for-each)遍历 for (int num : list) { System.out.println(num); } // 也可以手动使用迭代器 Iterator<Integer> it = list.iterator(); while (it.hasNext()) { System.out.println("Manual: " + it.next()); } } } ``` --- ### 输出结果: ``` 10 20 30 Manual: 10 Manual: 20 Manual: 30 ``` --- ### 解释: 1. **`Iterable<T>` 接口的作用**: - 它是 Java 集合框架的根接口之一。 - 只有一个抽象方法:`Iterator<T> iterator()`。 - 实现接口意味着对象可以被“遍历”。 2. **为什么需要实现 `Iterable`?** - 支持 `for-each` 循环语法,使代码更简洁、易读。 - 能与 Java 集合工具类(如 `Collections`, `Stream` 等)良好集成。 3. **`Iterator` 的作用**: - 提供统一的遍历机制。 - 包含 `hasNext()` `next()` 方法,安全地访问元素。 - 支持在遍历过程中调用 `remove()` 删除元素(可选操作)。 4. **注意事项**: - 如果你希望自定义遍历逻辑(比如逆序遍历),可以在 `iterator()` 方法中返回自定义的 `Iterator` 实现。 - 自定义 `Iterator` 时需注意 `ConcurrentModificationException` 的处理(可选,但推荐用于线程安全或修改检测场景)。 --- ### 进阶:自定义 Iterator(逆序遍历) ```java @Override public Iterator<Integer> iterator() { return new Iterator<Integer>() { private int currentIndex = numbers.size() - 1; @Override public boolean hasNext() { return currentIndex >= 0; } @Override public Integer next() { if (!hasNext()) { throw new NoSuchElementException(); } return numbers.get(currentIndex--); } }; } ``` 此时,`for-each` 循环将按**逆序**输出:30, 20, 10。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值