Java迭代器
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();
迭代期间的修改
有些集合不允许我们在通过"迭代器"进行迭代时修改集合。在这种情况下,我们下次调用Iterator
next()方法时将得到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() ); } } }