前言
阅读本篇文章,你需要对以下知识有所了解:
- 接口(这儿有)
- Iterator的使用
- Java 匿名内部类
构思
我们都知道,Iterator是一种迭代器,它的接口中有四种方法(JDK 1.8):
1public interface Iterator<E> {
2 boolean hasNext();
3 E next();
4 default void remove() { throw new UnsupportedOperationException("remove"); }
5 default void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action);while (hasNext()) action.accept(next()); }
6}
方法 |
返回值 |
作用 |
hasNext() |
boolean |
查找是否还有下一个元素,如果有,返回true,反则返回false |
next() |
Object |
返回下一个元素 |
remove() |
void |
删除当前指向的元素 |
forEachRemaining(Consumer<? super E> action) |
void |
对剩余的元素进行循环处理。传入一个Consumer参数,用于针对每个元素会执行的方法 |
现在创建一个数组:
1//创建数组
2String[] elements = {"苟利国家", "生死以,", "\n", "岂因祸福", "避趋之。"};
Q: 如果我们想利用Iterator遍历这个数组,主要需要调用Iterator的哪个方法?
A: hasNext()
用于查询是否还有下个元素、next()
用于返回下个元素。
实现
Iterator
迭代器是一个接口,所以接口中的hasNext()
方法和next()
方法是实现接口后必须重写的方法。
本行选读,可以不理解 而remove()
方法和forEachRemaining(Consumer<? super E> action)
方法使用了default
方法标记,说明它是有默认方法的,所以我们并不是必须要重写。
好,是时候打开你的IDE了:新建个项目,然后我们继续。
新建类
先别急着腿软,我们稍后会剖析整个过程。
占用你一分钟的时间,让我们新建两个类:
Main.java
1import java.util.Iterator;
2
3public class Main {
4 public static void main(String[] args) {
5 //创建数组
6 String[] elements = {"苟利国家", "生死以,", "\n", "岂因祸福", "避趋之。"};
7 //实例化Itr类,并将创建的数组传入
8 Itr itr = new Itr(elements);
9 //调用itr.iterator匿名内部类,并赋值到iterator
10 Iterator iterator = itr.iterator();
11 /**
12 * 当iterator.hasNext()返回值为false时,while循环有效
13 * 使用iterator.next()方法,返回下一个元素
14 */
15 while (iterator.hasNext()) {
16 System.out.print(iterator.next());
17 }
18 }
19}
Itr.java
1import java.util.Iterator;
2
3public class Itr implements Iterable {
4 private String[] elements;
5
6 /**
7 * 默认方法,用于实例化本类时传入指定数组
8 *
9 * @param elements 数组
10 */
11 Itr(String[] elements) {
12 this.elements = elements;
13 }
14
15 public Iterator iterator() {
16 return new Iterator() {
17 //指针,记录当前指示的数组下标
18 private Integer cursor = -1;
19
20 @Override
21 public boolean hasNext() {
22 /**
23 * 假设:当前cursor值为2,将cursor + 1 = 3
24 * 要判断elements的下标3位置是否为空,取elements的长度3并减1得2,证明elements的元素最多到2
25 * 判断:( cursor + 1 ) = 3 <= ( elements.length - 1 ) = ( 3 - 1 ) = 2
26 * 由于 3 !<= 2,所以返回false,即没有下一个元素
27 */
28 return cursor + 1 <= elements.length - 1;
29 }
30
31 @Override
32 public Object next() {
33 /**
34 * ++cursor为自增运算符,将cursor的值+1,将目标下标的元素返回
35 */
36 return elements[++cursor];
37 }
38 };
39 }
40
41}
现在运行主方法,你会得到运行结果:
1苟利国家生死以,
2岂因祸福避趋之。
剖析
扔下一个我刚刚画好的思维导图:
太长也得看。用这个思维导图配合代码中的注释,你一定能理解Iterator接口的编写和使用。
后语
Iterator是迭代器,而enumeration是枚举。
Iterator支持fail-fast机制,而Enumeration不支持。
fast-fail机制能确保迭代过程的线程安全:一个线程在进行迭代时,其它线程无法访问该类(抛出ConcurrentModificationException异常)。
更多关于fast-fail机制的知识,请点击这里。