Java中的迭代器(Iterators in Java)

原文地址:http://www.geeksforgeeks.org/iterators-in-java

迭代器是在Java中Collection框架中逐个检索元素,这里又三种迭代器。

枚举:

枚举是一种用于从遗留下来的集合(Vector,HashTable)中获取元素的。枚举首先是在JDK 1.0中开始表示的,剩下的包含在JDK 1.2中并包含更多的功能。枚举也用于指定输入流到SequenceInputStream。我们通过调用vector类或者(译者认为是or不是on)任意vector对象下的elements()方法来创建枚举对象。

// 这里"v"是一个Vector类对象。e是枚举接口类型的,并且指向“v”
Enumeration e = v.elements();

也就是说枚举接口有两个方法:

//测试是否这个枚举类型包含更多的元素
public boolean hasMoreElements();

// 返回这个枚举的下一个元素
// 抛出异常:NoSuchElementException
// 如果没有更多的元素表示
public Object nextElement();
// Java program to demonstrate Enumeration
import java.util.Enumeration;
import java.util.Vector;

public class Test
{
    public static void main(String[] args)
    {
        // Create a vector and print its contents
        Vector v = new Vector();
        for (int i = 0; i < 10; i++)
            v.addElement(i);
        System.out.println(v);

        // At beginning e(cursor) will point to
        // index just before the first element in v
        Enumeration e = v.elements();

        // Checking the next element availability
        while (e.hasMoreElements())
        {
            // moving cursor to next element
            int i = (Integer)e.nextElement();

            System.out.print(i + " ");
        }
    }
}

输出:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0 1 2 3 4 5 6 7 8 9 

枚举的缺点:

枚举类型只是针对遗留下的类型(Vector, Hashtable)。 因此它不是通用的迭代器。
在枚举类型中不能用remove操作。
只能用前进方向的迭代。

迭代器:

通用的迭代器可以用于任何的Collection对象。通过用迭代器,我们既可以做读操作,也可做移除操作。它是一种枚举类型的改进版本,这种枚举类型带有元素可移除的附加功能。

无论什么时候,我们想要枚举由接口(如Set, List, Queue, Deque还有所有Map接口的实现类)实现的Collection框架下的元素,我们就得用迭代器。迭代器是唯一可用的游标进入collection框架。

迭代器对象可以通过调用Collection接口中的iterator()方法来创建。

// Here "c" is any Collection object. itr is of
// type Iterator interface and refers to "c"
Iterator itr = c.iterator();

迭代接口定义了3个方法:

// Returns true if the iteration has more elements
public boolean hasNext();

// Returns the next element in the iteration
// It throws NoSuchElementException if no more 
// element present
public Object next();

// Remove the next element in the iteration
// This method can be called only once per call
// to next()
public void remove();

remove()方法可能抛出两个异常:

UnsupportedOperationException : 如果这个迭代器不支持remove操作。

IllegalStateException :如果下一个方法还没有被调用,或者在调用下一个方法之后remove方法已经被调用

// Java program to demonstrate Iterator
import java.util.ArrayList;
import java.util.Iterator;

public class Test
{
    public static void main(String[] args)
    {
        ArrayList al = new ArrayList();

        for (int i = 0; i < 10; i++)
            al.add(i);

        System.out.println(al);

        // at beginning itr(cursor) will point to
        // index just before the first element in al
        Iterator itr = al.iterator();

        // checking the next element availabilty
        while (itr.hasNext())
        {
            //  moving cursor to next element
            int i = (Integer)itr.next();

            // getting even elements one by one
            System.out.print(i + " ");

            // Removing odd elements
            if (i % 2 != 0)
               itr.remove(); 
        }
        System.out.println(); 
        System.out.println(al);
    }
}

输出:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0 1 2 3 4 5 6 7 8 9
[0, 2, 4, 6, 8]

迭代器的缺点:

只可以向前迭代。

迭代器不支持替换和添加新元素。.

列表迭代器(ListIterator):

它只用于List collection的实现类,如arraylist, linkedlist等,它提供两个方向的迭代。

当你想枚举List中的元素的时候,你就必须用ListIterator。ListIterator比iterator的方法多。

ListIterator对象可以通过List接口中的listIterator()方法来创建。

// Here "l" is any List object, ltr is of type
// ListIterator interface and refers to "l"
ListIterator ltr = l.listIterator();

ListIterator接口继承于Iterator接口,所以Iterator接口的三个方法在ListIterator都能用。另外ListIterator还有另外6个方法。

// Forward direction

// Returns true if the iteration has more elements
public boolean hasNext();

// same as next() method of Iterator
public Object next();

// Returns the next element index 
// or list size if the list iterator
// is at the end of the list
public int nextIndex();

// Backward direction

// Returns true if the iteration has more elements
// while traversing backward
public boolean hasPrevious();

// Returns the previous element in the iteration
// and can throws NoSuchElementException
// if no more element present
public Object previous();

// Returns the previous element index 
//  or -1 if the list iterator is at the 
// beginning of the list
public int previousIndex();

// Other Methods

// same as remove() method of Iterator
public void remove();

// Replaces the last element returned by 
// next() or previous() with the specified element 
public void set(Object obj);

// Inserts the specified element into the list at
// position before the element that would be returned 
// by next(),
public void add(Object obj);

很清楚,ListIterator从Iterator继承过来的三个方法(hasNext(), next(),和remove())在所有的接口中做的事情是一模一样的。hasPrevious()与前驱操作就是hasNext()与next()的模仿。former操作引用到(隐含的)光标(cursor)之前的元素,latter引用到光标之后的元素。previous操作往回移动光标,next是向后移动。

ListIterator没有当前元素这一说;它的游标位置总是在调用previous()返回的元素与调用next()返回的元素之间

set()方法可以抛出四种异常

UnsupportedOperationException:如果集合的操作不支持这种list迭代器

ClassCastException: 如果这个list不允许规定元素的类加入(If the class of the specified element prevents it from being added to this list)

IllegalArgumentException: 如果在有些规定的元素放慢不允许加入到这个list

IllegalStateException: 如果next或者previous被调用,或者在调用next或者previous之后再调用remove或者add方法

add()方法可以抛出三种异常

UnsupportedOperationException: 如果这种list iterator不支持add方法

ClassCastException: 如果这个list不允许规定元素的类加入(If the class of the specified element prevents it from being added to this list)

IllegalArgumentException: 如果由于某些原因这个元素不允许加入到list中

// Java program to demonstrate ListIterator
import java.util.ArrayList;
import java.util.ListIterator;

public class Test
{
    public static void main(String[] args)
    {
        ArrayList al = new ArrayList();
        for (int i = 0; i < 10; i++)
            al.add(i);

        System.out.println(al);

        // at beginning ltr(cursor) will point to
        // index just before the first element in al
        ListIterator ltr = al.listIterator();

        // checking the next element availabilty
        while (ltr.hasNext())
        {
            //  moving cursor to next element
            int i = (Integer)ltr.next();

            // getting even elements one by one
            System.out.print(i + " ");

            // Changing even numbers to odd and
            // adding modified number again in 
            // iterator
            if (i%2==0)
            {
                i++;  // Change to odd
                ltr.set(i);  // set method to change value
                ltr.add(i);  // to add
            }
        }
        System.out.println();
        System.out.println(al);
    }
}

输出:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0 1 2 3 4 5 6 7 8 9 
[1, 1, 1, 3, 3, 3, 5, 5, 5, 7, 7, 7, 9, 9, 9]

ListIterator的缺点:它是最强大的迭代器但是只能用于List的实现类,所以它不是一种通用的迭代器。

重要的共同点

1:请注意初始化任何迭代器引用讲指向一个collection的第一个元素的下标(index)。

2:我们不能创建Enumeration, Iterator, ListIterator的对象,因为它们是接口。我们用一些像elements(), iterator(), listIterator()这样的方法创建对象。这些方法拥有匿名的内部类,这些内部类继承于各自的接口并返回这个类的对象。这个可以通过下面的代码来证实,对于更多关于内部类的参考

// Java program to demonstrate iterators references
import java.util.Enumeration;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Vector;

public class Test
{
    public static void main(String[] args)
    {
        Vector v = new Vector();

        // Create three iterators
        Enumeration e = v.elements();
        Iterator  itr = v.iterator();
        ListIterator ltr = v.listIterator();

        // Print class names of iterators
        System.out.println(e.getClass().getName());
        System.out.println(itr.getClass().getName());
        System.out.println(ltr.getClass().getName());
    }
}

输出:

java.util.Vector$1
java.util.Vector$Itr
java.util.Vector$ListItr

The $ symbol in reference class name is a proof that concept of inner classes is used and these class objects are created.

Related Articles:
Iterator vs Foreach In Java
Retrieving Elements from Collection in Java (For-each, Iterator, ListIterator & EnumerationIterator)

你可能感兴趣的:(Java,Container)