java中迭代器

迭代器是一个能遍历数据集合的对象。

迭代器的基本概念:可以将迭代器看作是一个程序组件,它为用户提供了相关的方法,调用这些方法
就可以控制迭代过程。

注意:当直接使用Iterator(而不是通过一个增强的for循环间接使用)时,重要的是记住一个基本法则,如果对正在被迭代的集合进行结构上的改变即对集合使用clear(),add(),remove()等方法时,那么迭代器就不再合法。

java.util包中包含两个标准接口,分别是Iterator和ListIterator接口。

(1)Iterator接口中说明了三个方法(还有其他方法)hasNext,next,remove,.
hasNext查看迭代器是否有下一项返回,如果有,next返回指向它的引用。方法remove可以删除调用next时最后返回的项。
如果hasNxet返回true。则方法next将迭代器的游标移过下一个元素,并返回指向该元素的引用。如果没有,则NoSuchElementException异常
remove方法从迭代器指向的集合中删除迭代器返回的最后一个元素,每次调用next方法只能调用一次本方法。
(2)
ListIterator扩展了List的Iterator的功能。方法previous和hasPrevious使得对表从后向前遍历得以完成。
对于LinkedList来说,add是一个常数时间的操作,但对于ArrayList则代价昂贵。
set改变被迭代器看到的最后一个值,对ListIterator来说,很方便。
在这里插入图片描述

java.lang.Iterable接口
在这里插入图片描述

Iterable和Iterator的区别和联系。

==用Iterator模式实现遍历集合 ==

Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。
例如,如果没有使用Iterator,遍历一个数组的方法是使用索引: for(int i=0; i<array.size(); i++) { … get(i) … }
而访问一个链表(LinkedList)又必须使用while循环: while((e=e.next())!=null) { … e.data() … }

以上两种方法客户端都必须事先知道集合的内部结构,访问代码和集合本身是紧耦合,无法将访问逻辑从集合类和客户端代码中分离出来,每一种集合对应一种遍历方法,客户端代码无法复用。
更恐怖的是,如果以后需要把ArrayList更换为LinkedList,则原来的客户端代码必须全部重写。
解决以上问题,Iterator模式总是用同一种逻辑来遍历集合: for(Iterator it = c.iterater(); it.hasNext(); ) { … }

奥秘在于客户端自身不维护遍历集合的"指针",所有的内部状态(如当前元素位置,是否有下一个元素)都由Iterator来维护,而这个Iterator由集合类通过工厂方法生成,因此,它知道如何遍历整个集合。

客户端从不直接和集合类打交道,它总是控制Iterator,向它发送"向前",“向后”,"取当前元素"的命令,就可以间接遍历整个集合。

扫描二维码关注公众号,回复: 12575462 查看本文章

首先看看java.util.Iterator接口的定义:
public interface Iterator { boolean hasNext(); Object next(); void remove(); }

依赖前两个方法就能完成遍历,典型的代码如下:
for(Iterator it = c.iterator(); it.hasNext(); ) { Object o = it.next(); // 对o的操作… }

每一种集合类返回的Iterator具体类型可能不同,Array可能返回ArrayIterator,Set可能返回 SetIterator,Tree可能返回TreeIterator,但是它们都实现了Iterator接口,因此,客户端不关心到底是哪种 Iterator,它只需要获得这个Iterator接口即可,这就是面向对象的威力。

所有集合类都实现了 Collection 接口,而 Collection 继承了 Iterable 接口。

/**
 * Implementing this interface allows an object to be the target of
 * the "foreach" statement.
 *
 * @param <T> the type of elements returned by the iterator
 *
 * @since 1.5
 */
public interface Iterable<T> {
    
    
 
    /**
     * Returns an iterator over a set of elements of type T.
     *
     * @return an Iterator.
     */
    Iterator<T> iterator();
}

为什么一定要去实现Iterable这个接口呢?为什么不直接实现Iterator接口呢?

看一下JDK中的集合类,比如List一族或者Set一族,都是实现了Iterable接口,但并不直接实现Iterator接口。 仔细想一下这么做是有道理的因为Iterator接口的核心方法next()或者hasNext() 是依赖于迭代器的当前迭代位置的。 如果Collection直接实现Iterator接口,势必导致集合对象中包含当前迭代位置的数据(指针)。 当集合在不同方法间被传递时,由于当前迭代位置不可预置,那么next()方法的结果会变成不可预知。 除非再为Iterator接口添加一个reset()方法,用来重置当前迭代位置。 但即时这样,Collection也只能同时存在一个当前迭代位置。 而Iterable则不然,每次调用都会返回一个从头开始计数的迭代器。 多个迭代器是互不干扰的。

多个迭代器使用

List<String> nameList = new ArrayList<>();
        nameList.add("banana");
        nameList.add("cherry");
        nameList.add("apple");
        nameList.add("cherry");
        nameList.add("banana");
        Iterator<String> nameIterator = nameList.iterator();
        while (nameIterator.hasNext()){
    
    
            String currentName = nameIterator.next();
            int nameCount = 0;
            Iterator<String> countingIterator = nameList.iterator();
            while (countingIterator.hasNext()){
    
    
                String nextName = countingIterator.next();
                if (currentName.equals(nextName))
                    nameCount++;
            }
            System.out.println(currentName+"occurs"+nameCount+"times");
        }

猜你喜欢

转载自blog.csdn.net/weixin_45773632/article/details/109559967