1.Iterator
Iterator的定义如下:
public interface Iterator<E> {}
Iterator是一个接口,它是集合的迭代器。集合可以通过Iterator去遍历集合中的元素。Iterator提供的API接口如下:
-
forEachRemaining(Consumer<? super E> action):为每个剩余元素执行给定的操作,直到所有的元素都已经被处理或行动将抛出一个异常
-
hasNext():如果迭代器中还有元素,则返回true。
-
next():返回迭代器中的下一个元素
-
remove():从迭代器指向的collection中移除迭代器返回的最后一个元素(可选操作).。
注意:如果迭代删除每一个元素,就必须使用迭代器方式进行删除;,否则会出现ConcurrentModificationException - 并发修改异常
2.迭代器如何使用
2.1 迭代器正常遍历集合
public class demo {
public static void main(String[ ] args) {
ArrayList<Integer> arr=new ArrayList<>();
arr.add(10);
arr.add(20);
arr.add(30);
arr.add(40);
arr.add(50);
Iterator<Integer> it=arr.iterator();
while (it.hasNext()){
system.out.print(it.next()+"");
}
}
}
结果:
10 20 30 40 50
2.2 完全版迭代器可以一边遍历一边删除元素
public class demo {
public static void main(String[ ] args){
ArrayList<Integer> arr=new ArrayList<>();
arr.add(10);
arr.add(20);
arr.add(30);
arr.add(40);
arr.add(50);
system.out.println("Before iterate : " +arr);
Iterator<Integer> it=arr.iterator();
while (it.hasNext()){
System.out.print(it.next()+"");
it.remove();
}
system.out.println();//换行
system.out.println(arr);
}
}
结果如下:
Before iterate :[10,20,30,40,50]
10 20 30 40 50
[]
注意:
(1)Iterator只能单向移动。
(2)Iterator.remove()是唯一安全的方式来在迭代过程中修改集合;如果在迭代过程中以任何其它的方式修改了基本集合将会产生未知的行为。而且每调用一次next()方法,remove()方法只能被调用一次,如果违反这个规则将抛出一个异常。
2.3 foreach循环删除元素则会报错
public class demo {
public static void main(String[] args) {
ArrayList<Integer> arr=new ArrayList<>();
arr.add(10);
arr.add(20);
arr.add(30);
arr.add(40);
arr.add(50);
for (Integer integer : arr) {
system.out.print(integer);
arr.remove(integer);
}
}
}
for-each循环不支持集合在迭代过程中的结构性修改(如添加或删除元素)
使用迭代器(Iterator
)显式地删除元素:
Iterator<Integer> iterator = arr.iterator();
while (iterator.hasNext()) {
iterator.next(); // 移动到下一个元素
iterator.remove(); // 删除当前元素
}
在普通for循环,remove(int index)
方法可以删除元素,但是索引值会改变。
for (int i = arr.size() - 1; i >= 0; i--) {
arr.remove(i);
}
总结:
迭代器仅仅是遍历输出语句!本身并没有任何排序等其他功能,在数据结构的二叉树中别认为迭代器输出二叉树是因为迭代器会排序,是因为排序二叉树本身有序,迭代器仅仅是按照排序二叉树本身的排序规则输出罢了。
3. ListIterator
ListIterator是一个功能更加强大的, 它继承于Iterator接口,只能用于各种List类型的访问---专门为 List
集合设计。
可以通过调用 listIterator() 方法产生一个指向List开始处的ListIterator, 还可以调用listIterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator。
我们先来看一段关于ListIterator的描述:
ListIterator接口定义如下:
Interface ListIterator<E>{}
包含的方法有:
ListIterator
的主要方法包括:
-
boolean hasNext()
: 检查列表中是否还有下一个元素。 -
E next()
: 返回列表中的下一个元素,并将迭代器位置向前移动一位。 -
boolean hasPrevious()
: 检查列表中是否还有上一个元素。 -
E previous()
: 返回列表中的上一个元素,并将迭代器位置向后移动一位。 -
int nextIndex()
: 返回对下一个元素的索引(正向迭代中的索引)。 -
int previousIndex()
: 返回对上一个元素的索引(反向迭代中的索引)。 -
void add(E e)
: 在迭代器的当前位置插入指定的元素(可选操作)。 -
void set(E e)
: 用指定的元素替换迭代器最后返回的元素(可选操作)。 -
void remove()
: 从列表中移除迭代器最后返回的元素(可选操作)。
由以上定义我们可以推出ListIterator可以:
(1)双向移动(向前/向后遍历)。
(2)产生相对于迭代器在列表中指向的当前位置的前一个或后一个元素的索引。
(3)可以使用set()方法替换它访问过的最后一个元素。
(4)可以使用add()方法在next()方法返回的元素之前或previous()方法返回的元素之后插入一个元素.
例子:
import java.util.*;
public class TestListIterator{
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() + " ");//ccc bbb aaa
}
System.out.println();
it = a.listIterator(1);//调用listIterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator。
while (it.hasNext()) {
String t = it.next();
System.out.println(t);
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
bbb
ccc
After iterate : [aaa,bbb,kkk, nnn]
Iterator和ListIterator区别 我们在使用List,Set的时候,为了实现对其数据的遍历,我们经常使用到了Iterator(迭代器)。使用迭代器,你不需要干涉其遍历的过程,只需要每次取出一个你想要的数据进行处理就可以了。但是在使用的时候也是有不同的。List和Set都有iterator()来取得其迭代器。对List来说,你也可以通过listIterator()取得其迭代器,两种迭代器在有些时候是不能通用的,Iterator和ListIterator主要区别在以下方面:
-
ListIterator有add()方法,可以向List中添加对象,而Iterator不能
-
ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
-
ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
-
都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。
因为ListIterator的这些功能,可以实现对LinkedList等List数据结构的操作。其实,数组对象也可以用迭代器来实现。