Java可迭代
Java Iterable接口表示对象的集合,这些对象具有可迭代的含义,可以迭代。这意味着,实现JavaIterable
接口的类可以对其元素进行迭代。我们可以通过三种方式来迭代Java Iterable的对象:通过,通过从Iterable获取Java迭代器,或者通过调用Java IterableforEach()
方法。在本Java Iterable教程的后面,我们将看到所有这三种迭代方法的示例。
使用for-each循环迭代一个Iterable
迭代Java Iterable元素的第一种方法是通过Java for-each循环循环。下面的示例显示了如何通过Java for-each循环迭代Java List的元素。由于Java的List接口扩展了Collection接口,而Collection接口扩展了Iterable接口,因此List对象可以与for-each循环一起使用。
List<String> list = new ArrayList><(); list.add("one"); list.add("two"); list.add("three"); for( String element : list ){ System.out.println( element.toString() ); }
此示例首先创建一个新的"列表",并向其中添加3个元素。然后,它使用for-each循环来迭代List的元素,并打印出每个元素的toString()值。
通过迭代器迭代一个Iterable
迭代Java Iterable元素的第二种方法是通过调用Iterableiterator()
方法从其中获得Java Iterator。然后,我们可以像使用其他任何迭代器一样迭代该迭代器。我们可以在Java Iterator教程中阅读有关Java Iterator的更多信息。这是一个迭代Java Iterable元素的示例(此示例中为Java List):
List<String> list = new ArrayList><(); list.add("one"); list.add("two"); list.add("three"); Iterator<String> iterator = list.iterator(); while(iterator.hasNext()) { String element = iterator.next(); System.out.println( element ); }
通过其forEach()方法迭代Iterable
迭代Java Iterable元素的第三种方法是通过其forEach()
方法。 forEach()
方法采用Java Lambda表达式作为参数。对于Iterable中的每个元素,都会调用一次此lambda表达式。这是一个通过其forEach()方法迭代Iterable元素的示例:
List<String> list = new ArrayList><(); list.add("one"); list.add("two"); list.add("three"); list.forEach( (element) -> { System.out.println( element ); });
可迭代的接口定义
Java" Iterable"接口具有三种方法,其中仅一种方法需要实现。其他两个具有默认实现。这是Iterable接口的定义:
public interface Iterable<T> { Iterator<T> iterator(); Spliterator<T> spliterator(); void forEach(Consumer<? super T> action); }
我们必须实现的方法名为iterator()
。该方法必须返回一个Java迭代器,该迭代器可用于迭代实现Iterable接口的对象的元素。获取Iterator
是在幕后进行的,因此我们看不到完成的事情。当在for-each循环中使用" Iterable"时,Java编译器会负责为此生成代码。
Java中Iterable的实现
Java Iterable接口(java.lang.Iterable
)是Java Collections API的根接口之一。因此,Java中有几个实现Java"可迭代"接口的类。因此,可以对这些类的内部元素进行迭代。
还有几个Java接口扩展了Iterable接口。实现扩展Iterable接口的接口的类因此也实现Iterable接口。这样的类也可以迭代其元素。
"集合"接口扩展了"可迭代",因此"集合"的所有子类型也都实现了"可迭代"接口。例如,Java的List和Set接口都扩展了Collection接口,从而扩展了Iterable接口。
实现可迭代的接口
《 Java泛型》教程中的《实现可迭代接口》一文中介绍了如何实现此"可迭代"接口,以便可以将其与for-each循环一起使用。
在这里,我将仅向我们展示一个简单的Iterable实现示例:
public class Persons implements Iterable { private List<Person> persons = new ArrayList<Person>(); public Iterator<Person> iterator() { return this.persons.iterator(); } }
可以将" Persons"的一个实例与Java for-each循环一起使用,如下所示:
Persons persons = ... //obtain Persons instance with Person objects inside. for(Person person : persons) { // do something with person object. }
获取分离器
我们可以通过Java Iterable的spliterator()
方法获取Java Spliterator。在这里,我不会进入Spliterator界面,只是展示如何从Iterable中获取Spliterator:
List<String> list = new ArrayList><(); list.add("one"); list.add("two"); list.add("three"); Spliterator<String> spliterator = list.spliterator();
可迭代的性能
如果我们正在编写一些需要在一个紧密循环中多次迭代集合的代码,那么可以说每秒对Java列表进行数千次迭代,通过Java for-each循环对List
进行迭代比对列表进行迭代要慢通过一个标准的for循环,如下所示:(``)。
for(int i=0; i<list.size(); i++) { Object obj = list.get(i); }
for-each循环较慢的原因是,每次迭代都会调用List
iterator()方法,这将创建一个新的Iterator对象。与仅使用标准的for循环迭代" List"相比,每秒创建数千个,甚至每秒数百万次的新对象确实会降低性能。
对于偶尔迭代收集的大多数标准业务应用程序,此性能差异无关紧要。仅对于每秒执行数千次的非常紧密的循环才有意义。