Java基础之Iterable与Iterator
一、前言:
- Iterable :故名思议,实现了这个接口的集合对象支持迭代,是可迭代的。able结尾的表示 能...样,可以做...。
- Iterator: 在英语中or 结尾是都是表示 ...样的人 or ... 者。如creator就是创作者的意思。这里也是一样:iterator就是迭代者,我们一般叫迭代器,它就是提供迭代机制的对象,具体如何迭代,都是Iterator接口规范的。
二、Iterable:
- Iterable接口 (java.lang.Iterable) 是Java集合的顶级接口之一。我们首先看下这这个接口在JDK中的定义
package java.lang; public interface Iterable<AnyType>{
Iterator<AnyType> iterator();
}
- 可见,Iterable接口中只包含一个方法,就是一个iterator()方法,用来返回一个Iterator类型的对象,或者说返回一个实现了Iterator接口的对象。
- 一个集合对象要表明自己支持迭代,能有使用foreach语句的特权,就必须实现Iterable接口,表明我是可迭代的!然而实现Iterable接口,就必需为foreach语句提供一个迭代器。这个迭代器是用接口定义的 iterator方法提供的。也就是iterator方法需要返回一个Iterator对象。
- 实现了Iterable接口的类可以拥有增强的for循环,即只要实现了Iterable接口的类,就可以使用Iterator迭代器了。如
public static <AnyType> void print(Collection<AnyType> coll){
for(AnyType item: coll)
System.out.println(item);
}
注意!!!:这里的函数输入参数Collection<AnyType> coll
,其中coll是个接口变量。本来接口是不能用new来实例化一个接口的,即不能构造接口对象,但是可以用来声明接口变量,而且接口变量必须引用实现了接口的类对象。
- 集合Collection、List、Set都是Iterable的实现类,所以他们及其他们的子类都可以使用foreach进行迭代。
三、Iterator:
- 我们来看看jdk1.8之前,Iterator接口的定义:
package java.util;
public interface Iterator<AnyType>
{
boolean hasNext();
AnyType next();
void remove();
}
- 当编译器见到一个正在用于Iterable对象的增强的for循环的时候,它用对iterator()方法的调用来代替增强的for循环以得到一个Iterator对象,然后调用next和hasNext。我们可以给出iterator()方法的定义
因此,上面Iterable例程可以改写为
public static <AnyType> void print(Collection<AnyType> coll){
Iterator<AnyType> itr = coil.iterator();
while(itr.hasNext()) {
AnyType item = itr.next();
System.out.println(item);
}
}
- 包含的3个方法: hasNext , next , remove。remove按需求实现,一般它很少用到,以至于Eclipse接口方法自动补全时,都忽略了remove放方法。
1、每次在迭代前,先调用hasNext()探测是否迭代到终点(本次还能再迭代吗?)。
2、next方法不仅要返回当前元素,还要后移游标cursor
3、remove()方法用来删除最近一次已经迭代出的元素
4、迭代出的元素是原集合中元素的拷贝(重要)
5、配合foreach使用
四、二者的区别:
- Iterator是迭代器类,而Iterable是接口。
- 好多类都实现了Iterable接口,这样对象就可以调用iterator()方法,一般都是结合着用,比如 :
HashMap类就实现了Iterable接口,而要访问或打印出Map中所有内容时,就可以这样:
HashMap hashMap;
Iterator iter = hashMap.iterator();
while(iter.hashNext()) {
String s = iter.next();
}
Iterator iter = hashMap.iterator();
while(iter.hashNext()) {
String s = iter.next();
}
- 为什么一定要实现Iterable接口,为什么不直接实现Iterator接口呢?
看一下JDK中的集合类,比如List一族或者Set一族,都是实现了Iterable接口,但并不直接实现Iterator接口。
仔细想一下这么做是有道理的。
因为Iterator接口的核心方法next()或者hasNext() 是依赖于迭代器的当前迭代位置的。
如果Collection直接实现Iterator接口,势必导致集合对象中包含当前迭代位置的数据(指针)。
当集合在不同方法间被传递时,由于当前迭代位置不可预置,那么next()方法的结果会变成不可预知。
除非再为Iterator接口添加一个reset()方法,用来重置当前迭代位置。
但即时这样,Collection也只能同时存在一个当前迭代位置。
而Iterable则不然,每次调用都会返回一个从头开始计数的迭代器。
多个迭代器是互不干扰的。