Java迭代器

时间:2020-01-09 10:35:48  来源:igfitidea点击:

Java" Iterator"接口表示一个对象,该对象能够遍历一组Java对象,一次迭代一个对象。 Iterator接口是Java中用于迭代对象集合的最古老的机制之一(尽管不是最早的Iterator之前的Iterator)。

要使用Java迭代器,我们将必须从要迭代的对象集合中获取一个Iterator实例。获得的Iterator跟踪基础集合中的元素,以确保我们遍历所有元素。如果在遍历指向该集合的Iterator的过程中修改基础集合,则Iterator通常会检测到它,并在下次尝试从Iterator获取下一个元素时引发异常。

Java Iterator核心方法

Java Iterator接口相当简单。 Iterator接口的核心方法是:

方法描述
hasNext()如果迭代器具有更多元素,则返回“ true”,否则返回“ false”。
next()从迭代器中返回下一个元素
remove()
forEachRemaining()迭代迭代器中的所有剩余元素,并调用Java Lambda Expression ,将其余每个元素作为参数传递给lambda表达式。

以下各节将介绍每种方法。

获取迭代器

通常,这是通过从包含多个嵌套对象的Java对象中获取"迭代器"来与之交互的方式。标准Java集合接口"集合"包含一个称为" iterator()"的方法。通过调用iterator(),我们可以从给定的Collection中获得一个迭代器。

我们还可以从许多Java Collection数据结构中获取一个"迭代器",例如列表,集合,地图,队列,双端队列或者地图。

以下是从各种Java集合类型获取Java迭代器的一些示例:

List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");

Iterator<String> iterator = list.iterator();

Set<String> set = new HashSet<>();
set.add("one");
set.add("two");
set.add("three");

Iterator<String> iterator2 = set.iterator();

迭代一个迭代器

我们可以使用while循环在Iterator中迭代对象。这是一个使用while循环迭代JavaIterator的元素的示例:

Iterator iterator = list.iterator();

while(iterator.hasNext()) {
    Object nextObject = iterator.next();

}

上面的Java示例中有两种方法要注意。第一种方法是Iterator的hasNext()方法,如果Iterator包含更多元素,则返回true。换句话说,如果Iterator尚未对集合中的所有元素进行迭代,则从hasNext()方法获得的Iterator将返回true。如果迭代器已经遍历了基础集合中的所有元素,则" hasNext()"方法将返回" false"。

注意的第二种方法是next()方法。 " next()"方法返回"迭代器"正在迭代的集合的下一个元素。

迭代顺序

遍历Java Iterator中包含的元素的顺序取决于提供Iterator的对象。例如,从"列表"获得的迭代器将以该元素在内部存储在"列表"中的顺序来遍历该"列表"的元素。另一方面,从Set中获取的Iterator不能保证Set中元素的确切顺序。

Java列表迭代器

这是一个从List实例获取Java Set迭代器的示例:

List list = new ArrayList();

list.add("123");
list.add("456");
list.add("789");

Iterator iterator = list.iterator();

Java Set迭代器

这是一个从Set实例获取Java Set迭代器的示例:

Set set = new HashSet();

set.add("123");
set.add("456");
set.add("789");

Iterator iterator = set.iterator();

迭代期间的修改

有些集合不允许我们在通过"迭代器"进行迭代时修改集合。在这种情况下,我们下次调用Iteratornext()方法时将得到ConcurrentModificationException。以下示例在执行时会导致ConcurrentModificationException

List<String> list = new ArrayList<>();

list.add("123");
list.add("456");
list.add("789");

Iterator<String> iterator = list.iterator();

while(iterator.hasNext()) {
    String value = iterator.next();

    if(value.equals("456")){
        list.add("999");
    }
}

抛出ConcurrentModificationException的原因是,如果在通过Iterator迭代时修改了Collection,则Iterator与集合不同步。

迭代期间删除元素

JavaIterator接口有一个remove()方法,该方法使我们可以从基础集合中删除next()返回的元素。调用remove()不会引发ConcurrentModificationException。这是一个在其Iterator的迭代过程中从集合中删除元素的示例:

List<String> list = new ArrayList<>();

list.add("123");
list.add("456");
list.add("789");

Iterator<String> iterator = list.iterator();

while(iterator.hasNext()) {
    String value = iterator.next();

    if(value.equals("456")){
        iterator.remove();
    }
}

forEachRemaining()

Java Iterator的forEachRemaining()方法可以在内部迭代迭代器中剩余的所有元素,并为每个元素调用Java Lambda Expression作为参数传递给forEachRemaining()。这是使用Java迭代器forEachRemaining()方法的示例:

List<String> list = new ArrayList<>();
list.add("Jane");
list.add("Heidi");
list.add("Hannah");

Iterator<String> iterator = list.iterator();
        
iterator.forEachRemaining((element) -> {
    System.out.println(element);
});

ListIterator

Java还包含一个名为ListIterator的接口,该接口扩展了Iterator接口。 Java ListIterator接口代表双向迭代器,意味着可以其中前后导航元素的迭代器。我不会在这里详细介绍ListIterator接口,但是我将向我们展示如何使用它的快速示例:

List<String> list = new ArrayList<>();
list.add("Jane");
list.add("Heidi");
list.add("Hannah");

ListIterator<String> listIterator = list.listIterator();
        
while(listIterator.hasNext()) {
    System.out.println(listIterator.next());
}
        
while(listIterator.hasPrevious()) {
    System.out.println(listIterator.previous());
}

如我们所见,该示例首先循环遍历所有元素的ListIterator,然后再次遍历所有元素回到第一个元素。

在自己的类中实现Iterator接口

如果我们有特殊的定制类型的集合,则可以自己实现Java Iterator接口,以创建一个可以迭代自定义集合的元素的Iterator。在本节中,我将向我们展示Java Iterator接口的超简单自定义实现,使我们对自己实现Iterator接口的外观印象深刻。

我将为其实现Iterator的集合是标准Java List。这将不是一个完美的实现,因为它将无法在迭代过程中检测到List内容的更改,但这足以使我们了解Iterator实现的外观。这里是:

import java.util.Iterator;
import java.util.List;

public class ListIterator <T> implements Iterator<T> {

    private List<T> source = null;
    private int index = 0;

    public ListIterator(List<T> source){
        this.source = source;
    }

    @Override
    public boolean hasNext() {
        return this.index < this.source.size();
    }

    @Override
    public T next() {
        return this.source.get(this.index++);
    }

}

这是上面的ListIterator的迭代过程中的外观示例:

import java.util.ArrayList;
import java.util.List;

public class ListIteratorExample {

    public static void main(String[] args) {
        List<String> list = new ArrayList();

        list.add("one");
        list.add("two");
        list.add("three");

        ListIterator<String> iterator = new ListIterator<>(list);
        while(iterator.hasNext()) {
            System.out.println( iterator.next() );
        }

    }
}