likes
comments
collection
share

迭代器Iterator和Iterable有什么区别?

作者站长头像
站长
· 阅读数 9

Java语言中,Iterator和Iterable都是用来遍历集合类数据结构的接口。虽然它们有很多相似的地方,但在具体实现中却有着一些不同之处。本文将详细分析它们的区别,并提供相应的代码示例。

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("apple");
list.add("banana");
list.add("orange");

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

输出结果:

apple
banana
orange

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("apple");
list.add("banana");
list.add("orange");

for(String fruit : list){
    System.out.println(fruit);
}

/* 写得更浅显易懂点,就是:
list.forEach(new Consumer<String>() {
    @Override
    public void accept(String str) {
        System.out.println(str);
    }
});*/

输出结果:

apple
banana
orange

与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("apple");
list.add("banana");
list.add("orange");

// 使用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); 
}

输出结果:

apple
banana
orange

apple
banana
orange

从上面的代码可以看出,Iterator和Iterable都可以用于遍历列表,并且输出的结果是相同的。但是,Iterator可以在迭代过程中动态地修改集合的内容,而Iterable则不能。此外,Iterator可以在遍历时删除元素,而Iterable不支持删除操作。

4. 总结

迭代器Iterator和Iterable有什么区别?

Iterator和Iterable是Java编程语言中两个非常重要的接口,都是用于遍历集合类数据结构的。它们虽然有着很多相似的地方,但在实现细节和代码便捷性方面有所不同。

在实际应用中,我们需要根据具体的业务场景来选择使用哪个接口。如果需要进行单向遍历、修改等操作,可以选择使用Iterator接口;如果需要进行双向遍历、只读操作等操作,则可以选择使用Iterable接口。

无论哪个接口,都可以通过Java提供的语法糖来简化代码,使得集合遍历更加便捷、可读、易维护。