1. Iterator接口
Iterator的作用是遍历集合中的元素,它为集合提供了一种访问元素的方法,可以按顺序访问集合中的每一个元素。Iterator可以处理任何实现了Iterable接口的集合,如List、Set、Map等。Iterator可以在遍历集合时动态地修改集合的内容,如添加、删除元素等。
Iterator接口是Java编程语言中一个非常重要的接口,它定义了遍历一个集合中所有元素的方法。以下是Iterator接口的主要方法:
public interface Iterator<E> {
boolean hasNext() // 如果还有元素可以迭代,则返回true
E next() // 返回迭代的下一个元素
void remove() // 从迭代器指向的集合中删除最后一个元素
}
Iterator 接口,JDK 1.2 的时候就有了,用来改进 Enumeration 接口:
允许删除元素(增加了 remove 方法)
优化了方法名(Enumeration 中是 hasMoreElements 和 nextElement,不简洁)
Iterator接口是一个单向遍历接口,只能向前遍历集合中的元素,而无法回溯或反向遍历。此外,只读集合无法使用Iterator进行修改操作。
以下是使用Iterator接口遍历ArrayList集合的示例代码:
List<String> list = new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String fruit = iterator.next();
System.out.println(fruit);
}
输出结果:
aa
bb
cc
2. Iterable接口
Iterable的作用是提供一种遍历集合的方式,它是一个接口,用于表示实现了该接口的对象都可以被迭代。Iterable接口为集合提供了一种统一的遍历方式,从而可以在不同的集合间实现通用的迭代操作。
Iterable接口是Java编程语言中另一个非常重要的接口,仅有一个方法的声明,它定义了一个可以被迭代的对象,并提供了一个默认的iterator()方法,优化了遍历操作的可读性。以下是Iterable接口的主要方法:
Iterator<T> iterator() // 返回一个Iterator对象用于迭代集合
JDK 1.8 时,Iterable 接口中新增了 forEach 方法。该方法接受一个 Consumer 对象作为参数,用于对集合中的每个元素执行指定的操作。该方法的实现方式是使用 for-each 循环遍历集合中的元素,对于每个元素,调用 Consumer 对象的 accept 方法执行指定的操作。
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
该方法实现时首先会对 action 参数进行非空检查,如果为 null 则抛出 NullPointerException 异常。然后使用 for-each 循环遍历集合中的元素,并对每个元素调用 action.accept(t) 方法执行指定的操作。由于 Iterable 接口是 Java 集合框架中所有集合类型的基本接口,因此该方法可以被所有实现了 Iterable 接口的集合类型使用。它对 Iterable 的每个元素执行给定操作,具体指定的操作需要自己写Consumer接口通过accept方法回调出来。
使用Iterable接口时,我们可以直接使用for-each循环来遍历集合,来简化代码。例如:
List<String> list = new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
for(String fruit : list){
System.out.println(fruit);
}
/* 写得更浅显易懂点,就是:
list.forEach(new Consumer<String>() {
@Override
public void accept(String str) {
System.out.println(str);
}
});*/
输出结果:
aa
bb
cc
与Iterator接口不同,Iterable接口是双向迭代器,可以进行正向和反向遍历。但Iterable接口仅用于遍历读取操作,无法进行修改操作。
3. 区别分析
在上述两个接口中,最重要的区别是它们对代码的便捷性有所不同。Iterator是一个单独的迭代器接口,需要手动调用next()、hasNext()和remove()等方法来遍历集合中的元素,需要写很多重复的代码。而Iterable接口则采用了for-each循环语法来简化代码,使得开发者更加轻松地遍历集合。
此外,在使用时,Iterator接口只能遍历一次集合,而Iterable接口可以多次遍历集合。由于Iterator接口是通过遍历每个元素来访问集合内部元素的,因此无法反复遍历。相比之下,Iterable接口中的iterator()方法返回的是一个新的迭代器对象,因此可以反复地使用for-each语句来遍历集合,从而更加灵活方便。
最后,在对只读集合进行操作时,Iterable接口提供的for-each循环语法更为便捷。在这种情况下,Iterator接口需要通过while循环遍历集合,并且无法在同一代码块中操作集合。因此,Iterable接口具有更好的可读性和可维护性。
下面是一个用Iterable接口遍历LinkedList集合的示例代码:
List<String> list = new LinkedList<>();
list.add("aa");
list.add("bb");
list.add("cc");
// 使用Iterator遍历列表
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
}
// 使用Iterable遍历列表
Iterable<String> iterable = list;
for (String item : iterable) {
System.out.println(item);
}
输出结果:
aa
bb
cc
aa
bb
cc
从上面的代码可以看出,Iterator和Iterable都可以用于遍历列表,并且输出的结果是相同的。但是,Iterator可以在迭代过程中动态地修改集合的内容,而Iterable则不能。此外,Iterator可以在遍历时删除元素,而Iterable不支持删除操作。
4. 总结
Iterator和Iterable是Java编程语言中两个非常重要的接口,都是用于遍历集合类数据结构的。它们虽然有着很多相似的地方,但在实现细节和代码便捷性方面有所不同。
在实际应用中,我们需要根据具体的业务场景来选择使用哪个接口。如果需要进行单向遍历、修改等操作,可以选择使用Iterator接口;如果需要进行双向遍历、只读操作等操作,则可以选择使用Iterable接口。
无论哪个接口,都可以通过Java提供的语法糖来简化代码,使得集合遍历更加便捷、可读、易维护。