ZetCode

Java 外部迭代器 vs 内部迭代器

最后修改于 2024 年 1 月 27 日

Java 外部迭代器 vs 内部迭代器 展示了 Java 中外部迭代器和内部迭代器之间的区别。

迭代器 是一个允许程序员遍历容器(例如列表和映射)的对象。

迭代器类型

迭代器有两种类型:外部的和内部的。 外部迭代器是主动的,内部迭代器是被动的。

当客户端(即程序员)控制迭代时,该迭代器称为外部迭代器。 当迭代器控制迭代时,它被称为内部迭代器。

通常,建议使用内部迭代器而不是外部迭代器。 内部迭代更不易出错,更易读,并且需要更少的代码。 另一方面,外部迭代器有时更灵活; 例如,在循环中为两个集合执行操作时。

Java 外部迭代器示例

以下示例显示了外部迭代器的用法。

JavaExternalIterationEx.java
package com.zetcode;

import java.util.List;

public class JavaExternalIterationEx {

    public static void main(String[] args) {

        List<String> words = List.of("hello", "sky", "there", "den", "sky");

        for (String word: words) {

            System.out.printf("The word %s has %d characters%n",
                    word, word.length());
        }
    }
}

在该示例中,我们使用外部迭代器遍历单词列表,并打印其元素及其字符大小。

The word hello has 5 characters
The word sky has 3 characters
The word there has 5 characters
The word den has 3 characters
The word sky has 3 characters

ConcurrentModificationException

当我们使用带有增强 for 循环的外部迭代并修改集合的元素时,可能会收到 ConcurrentModificationException

JavaExternalIterationEx2.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class JavaExternalIterationEx2 {

    public static void main(String[] args) {

        List<String> words = new ArrayList<>(Arrays.asList("pen", "pencil",
                "sky", "blue", "sky", "dog"));

        for (String word: words) {

            if ("sky".equals(word)) {

                words.remove(word);
            }
        }

        System.out.println(words);
    }
}

在该示例中,我们要从列表中删除所有等于“sky”的单词。 这是为了演示目的; 因为自 Java 8 以来,我们可以使用 removeIf 方法轻松删除元素:words.removeIf(e -> "sky".equals(e));

Exception in thread "main" java.util.ConcurrentModificationException

运行该示例会导致 ConcurrentModificationException

Java 中其他形式的外部迭代有效。

Iterator<String> iter = words.iterator();

while (iter.hasNext()) {
    String s = iter.next();

    if ("sky".equals(s)) {
        iter.remove();
    }
}

该示例可以使用带有 while 循环的旧式迭代正常工作。

for (int i=words.size() - 1; i>=0; i--) {

    if ("sky".equals(words.get(i))) {
        words.remove(i);
    }
}

它也可以与传统的 for 循环一起使用。

另请注意,在这种情况下使用 for each 循环不会导致所有语言都出现错误。 例如,Python 3 或 Perl 6 可以正常工作。 另一方面,JavaScript 和 C++ 也会最终导致错误。

extit.py
#!/usr/bin/python3

words = ["pen", "pencil", "dog", "sky", "blue", "sky"]

print(len(words))

for word in words:
    if word == "sky":
        words.remove(word)

print(words)
print(len(words))

这是 Python 3 中的等效代码。它可以正常工作。

Java 内部迭代器示例

在以下示例中,我们使用内部迭代器。

JavaInternalIteratorEx.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class JavaInternalIteratorEx {

    public static void main(String[] args) {

        List<String> words = List.of("hello", "sky", "there", "den", "sky");

        words.stream().forEach(e -> 
                System.out.printf("The word %s has %d characters %n", e, e.length()));
    }
}

该示例遍历列表的所有元素并打印它们及其大小。

JavaInternalIteratorEx2.java
package com.zetcode;

import java.util.List;
import java.util.stream.Collectors;

public class JavaInternalIteratorEx2 {

    public static void main(String[] args) {

        List<String> words = List.of("hello", "sky", "there", "den", "sky");

        List<String> words2 = words.stream().filter(e -> !"sky".equals(e))
                                    .collect(Collectors.toList());

        System.out.println(words2);
    }
}

使用现代函数式 Java,我们展示了如何创建一个新的不可变列表,其中不包含“sky”单词。

[hello, there, den]

来源

Java 迭代器 - 语言参考

在本文中,我们讨论了 Java 中的外部迭代器和内部迭代器。

作者

我叫 Jan Bodnar,是一名充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有Java教程