一、Iterable 接口
1、Iterable 是 java.lang 包下面的一个接口,实现此接口可使对象成为“ for-each循环”语句的目标,同时里面还有获取迭代器的方法。
方法说明:
Iterator<T> iterator():获取迭代器对象
default void forEach(Consumer<? super T> action)
default Spliterator<T> spliterator()
其中default 方法的实现如下:
二、Iterator 接口
1、概述
(1)Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素,它替代了 JCF 中的 Enumeration 接口。
(2)GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。 迭代器模式,就是为容器而生。迭代器(Iterator)有时又称为游标(cursor),提供一种方法访问一个容器(container)对象中各个元素,而又不暴露该对象的内部细节。
(3)Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了
Iterator接口的对象。
(4)Iterator 仅用于遍历集合, Iterator 本身并不提供承装对象的能力。如果需要创建Iterator 对象,则必须有一个被迭代的集合。
(5)集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
2、Iterator 接口的方法
方法概述:
boolean hasNext():这个方法是在遍历的时候,判断是否还有更多的元素
E next(): 返回下一个元素
default void remove():这里涉及到了jdk8的特性,在接口定义中,将方法描述为default-虚拟扩展方法,
就可以在接口中进行默认实现,从而提高接口的扩展性,避免在接口扩展的时候,破坏原有的实现。
default void forEachRemaining(Consumer<? super E> action):对剩余的每个元素执行给定的操作,这个方面一般都用不到,不做具体描述。
注意:
(1)在调用it.next()方法之前必须要调用it.hasNext()进行检测。若不调用,且下一条记录无效,直接调用it.next()会抛出NoSuchElementException异常
(2)集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前;
(3)内部定义了remove(),可以在遍历的时候,删除集合中的元素。此方法不同于集合直接调用remove();
3、迭代器的执行原理
4、Iterator 接口的 remove() 方法
代码示例:
1 Iterator iter = coll.iterator();//回到起点
2 while(iter.hasNext()){
3 Object obj = iter.next();
4 if(obj.equals("Tom")){
5 iter.remove();
6 }
7 }
注意:
(1)Iterator可以删除集合的元素, 但是是遍历过程中通过迭代器对象的remove方法, 不是集合对象的remove方法。
(2)如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,再调用remove都会报IllegalStateException。
5、使用 foreach 循环遍历集合元素
(1)Java 5.0 提供了 foreach 循环迭代访问 Collection和数组;
(2)遍历操作不需获取Collection或数组的长度,无需使用索引访问元素;
(3)遍历集合的底层调用Iterator完成操作;
(4)foreach还可以用来遍历数组。
6、集合中的迭代器
迭代器是为容器遍历而生,用以方便的实现对容器内元素的遍历操作。类似于“公交车上的售票员”、“飞机上的空姐”,他们只为关注当前“容器”中的乘客,可以“访问”每一位乘客。例如:公交车上的售票员走到每个座位之前,看看是否有乘客,如果有检查该乘客,如果该乘客未购票,可以请他下车,也只能请刚刚检查过的乘客下车。每一类集合都有自己的迭代器,迭代器是为对应的集合服务的,因此迭代器都是作为对应集合的内部类定义的。
示例:摘取关键代码 ArrayList 的内部迭代器 Itr。
三、ListIterator 接口
它在 Iterator 基础上增加方法如下:
// 是否有前一个元素(可理解为从后往前遍历)
boolean hasPrevious();
// 获取前一个元素
E previous();
// 返回对 next() 的后续调用将返回的元素的索引
// 如果列表迭代器位于列表的末尾,则返回列表大小
int nextIndex();
// 返回对 previous() 的后续调用将返回的元素的索引
// 如果列表迭代器位于列表的开头,则返回 -1
int previousIndex();
// 用指定的元素替换 next() 或 previous() 返回的最后一个元素
void set(E e);
// 插入指定元素到列表中
void add(E e);
5个方法。通过前3个方法可以进行向前遍历元素,后面两个 set 和 add 可以插入元素,但是 set 是将元素插入到链表的最后位置,add 是插入到当前返回的元素之前。
注意:迭代器的游标在元素之间,如下:
/** Element(0) Element(1) Element(2) ... Element(n-1)* cursor positions: ^ ^ ^ ^ ^*/
四、Iterator 接口与 ListIterator 接口区别与联系