大白话 | 课堂实践:使用 Iterator 对数组进行遍历

本贴最后更新于 1900 天前,其中的信息可能已经东海扬尘

前言

阅读本篇文章,你需要对以下知识有所了解:

  • 接口(这儿有
  • Iterator 的使用
  • Java 匿名内部类

构思

我们都知道,Iterator 是一种迭代器,它的接口中有四种方法(JDK 1.8):

public interface Iterator<E> {
	boolean hasNext();
	E next();
	default void remove() { throw new UnsupportedOperationException("remove"); }
        default void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action);while (hasNext()) action.accept(next()); }
}
方法 返回值 作用
hasNext() boolean 查找是否还有下一个元素,如果有,返回 true,反则返回 false
next() Object 返回下一个元素
remove() void 删除当前指向的元素
forEachRemaining(Consumer<? super E> action) void 对剩余的元素进行循环处理。传入一个 Consumer 参数,用于针对每个元素会执行的方法

现在创建一个数组:

//创建数组
String[] elements = {"苟利国家", "生死以,", "\n", "岂因祸福", "避趋之。"};

Q: 如果我们想利用 Iterator 遍历这个数组,主要需要调用 Iterator 的哪个方法?

A: hasNext() 用于查询是否还有下个元素、next() 用于返回下个元素。

实现

Iterator 迭代器是一个接口,所以接口中的 hasNext() 方法和 next() 方法是实现接口后必须重写的方法。
本行选读,可以不理解remove() 方法和 forEachRemaining(Consumer<? super E> action) 方法使用了 default 方法标记,说明它是有默认方法的,所以我们并不是必须要重写。

好,是时候打开你的 IDE 了:新建个项目,然后我们继续。

新建类

先别急着腿软,我们稍后会剖析整个过程。
占用你一分钟的时间,让我们新建两个类:

Main.java

import java.util.Iterator;

public class Main {
    public static void main(String[] args) {
        //创建数组
        String[] elements = {"苟利国家", "生死以,", "\n", "岂因祸福", "避趋之。"};
        //实例化Itr类,并将创建的数组传入
        Itr itr = new Itr(elements);
        //调用itr.iterator匿名内部类,并赋值到iterator
        Iterator iterator = itr.iterator();
        /**
         * 当iterator.hasNext()返回值为false时,while循环有效
         * 使用iterator.next()方法,返回下一个元素
         */
        while (iterator.hasNext()) {
            System.out.print(iterator.next());
        }
    }
}

Itr.java

import java.util.Iterator;

public class Itr implements Iterable {
    private String[] elements;

    /**
     * 默认方法,用于实例化本类时传入指定数组
     *
     * @param elements 数组
     */
    Itr(String[] elements) {
        this.elements = elements;
    }

    public Iterator iterator() {
        return new Iterator() {
            //指针,记录当前指示的数组下标
            private Integer cursor = -1;

            @Override
            public boolean hasNext() {
                /**
                 * 假设:当前cursor值为2,将cursor + 1 = 3
                 * 要判断elements的下标3位置是否为空,取elements的长度3并减1得2,证明elements的元素最多到2
                 * 判断:( cursor + 1 ) = 3 <= ( elements.length - 1 ) = ( 3 - 1 ) = 2
                 * 由于 3 !<= 2,所以返回false,即没有下一个元素
                 */
                return cursor + 1 <= elements.length - 1;
            }

            @Override
            public Object next() {
                /**
                 * ++cursor为自增运算符,将cursor的值+1,将目标下标的元素返回
                 */
                return elements[++cursor];
            }
        };
    }

}

现在运行主方法,你会得到运行结果:

苟利国家生死以,
岂因祸福避趋之。

剖析

扔下一个我刚刚画好的思维导图:

7.png

太长也得看。用这个思维导图配合代码中的注释,你一定能理解 Iterator 接口的编写和使用。

后语

Iterator 是迭代器,而 enumeration 是枚举。
Iterator 支持 fail-fast 机制,而 Enumeration 不支持。
fast-fail 机制能确保迭代过程的线程安全:一个线程在进行迭代时,其它线程无法访问该类(抛出 ConcurrentModificationException 异常)。
更多关于 fast-fail 机制的知识,请点击这里

  • 大白话
    17 引用 • 27 回帖
  • 课堂实践
    1 引用
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3187 引用 • 8213 回帖
  • 原理
    16 引用 • 44 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...