Java集合框架之Iterator和ListIterator

Deadly 提交于 2020-03-01 02:48:00

一、前言

       迭代器是一个对象,它可以让你遍历一个容器并且有选择性的删除 容器 中的元素,而我们不需要知道 容器 的内部结构.Java有两种原生的迭代器:Iterator和ListIterator, 其中 ListIterator继承自 Iterator.

二、Iterator接口

    Iterator 通常被称为轻量级对象,因为创建它的开销比较小.可以通过调用容器 iterator()方法来获取它的Iterator.

      下面是Iterator接口定义:

       代码清单-1

public interface Iterator<E> {
    boolean hasNext();

    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}
          Java的 Iterator只能单向移动,它只能用来:
    (1)使用容器的 iterator ()方法返回它的Iterator.Iterator将返回容器的第一个元素.
    (2)使用next()方法返回容器的下一个元素.
    (3)使用hasNext()方法检查容器中是否还有元素. 如果有,hasNext()方法返回 true.
    (4)使用 remove()方法删除由 next()方法新近返回的元素.

    下面来看一个使用示例:

    代码清单-2   

public class IteratorExample {
    public static void main(String[] args) {
        ArrayList<String> a = new ArrayList<String>();
        a.add("aaa");
        a.add("bbb");
        a.add("ccc");
        System.out.println("Before iterate : " + a);
        Iterator<String> it = a.iterator();
        while (it.hasNext()) {
            String t = it.next();
            if ("bbb".equals(t)) {
                it.remove();
            }
        }
        System.out.println("After iterate : " + a);
    }
}

    输出结果如下:  

Before iterate : [aaa, bbb, ccc]
After iterate : [aaa, ccc]

    注意:Iterator.remove()是唯一安全的方式来在迭代过程中修改集合;如果在迭代过程中以任何其它的方式修改了基本集合将会产生未知的行为.而且每调用一次next()方法,remove()方法只能被调用一次,如果违反这个规则将抛出一个异常.

三、ListIterator接口

    ListIterator是一个功能更加强大的迭代器, 它只能用于各种List类型的访问。可以通过调用listIterator()方法产生一个指向List开始处的ListIterator, 还可以调用listIterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator.

    ListIterator接口定义如下:

            代码清单-3  
public interface ListIterator<E> extends Iterator<E> {
    boolean hasNext();

    E next();

    boolean hasPrevious();

    E previous();

    int nextIndex();

    int previousIndex();

    void remove();

    void set(E e);

    void add(E e);
    
}

    由以上定义我们可以推出ListIterator可以:

    (1)双向移动.

    (2)产生相对于迭代器在列表中指向的当前位置的前一个和后一个元素的索引.

    (3)可以使用set()方法替换它访问过的最后一个元素.

    (4)可以使用add()方法在next()方法返回的元素之前或previous()方法返回的元素之后插入一个元素.

    下面就简单演示所有这些功能:

         代码清单-4

public class ListIteratorExample {

    public static void main(String[] args) {
        ArrayList<String> a = new ArrayList<String>();
        a.add("aaa");
        a.add("bbb");
        a.add("ccc");
        System.out.println("Before iterate : " + a);
        ListIterator<String> it = a.listIterator();
        while (it.hasNext()) {
            System.out.println(it.next() + ", " + it.previousIndex() + ", " + it.nextIndex());
        }
        while (it.hasPrevious()) {
            System.out.print(it.previous() + " ");
        }
        System.out.println();
        it = a.listIterator(1);
        while (it.hasNext()) {
            String t = it.next();
            if ("ccc".equals(t)) {
                it.set("nnn");
            } else {
                it.add("kkk");
            }
        }
        System.out.println("After iterate : " + a);
    }
}

    输出结果如下:

Before iterate : [aaa, bbb, ccc]
aaa, 0, 1
bbb, 1, 2
ccc, 2, 3
ccc bbb aaa 
After iterate : [aaa, bbb, kkk, nnn]

四、Iterator使用场

    在以下情况下可以使用Iterator接口代替for-each结构:

    (1)删除当前的元素.for-each结构隐藏了迭代器, 所以你不能调用remove()方法. 因此for-each结构无法用于过滤.
    (2)并行地迭代多个集合.

        下面的代码片段展示了如何使用一个迭代器来过滤任意一个集合——即遍历这个集合并删除指定元素.

        代码清单-5

static void filter(Collection<?> c) {
    for (Iterator<?> it = c.iterator(); it.hasNext(); )
        if (!cond(it.next()))
            it.remove();
}
             以上代码是多态的, 意味着它对任何集合都起作用, 而不用去考虑具体的实现.可见使用Java集合框架来编写多态的算法是多么的简单.

五、参考资料

                               http://docs.oracle.com/javase/tutorial/collections/interfaces/collection.html

        《Thinking In Java》




   






易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!