Java中在迭代时添加元素的3种方法

迭代List是Java中的常见操作,但是在迭代时向其中添加元素需要仔细考虑,以避免出现异常并确保代码的正确性。

在本教程中,我们将讨论在迭代期间向集合添加元素的几种方法。

1、使用ListIterator类
一种常见的方法是ListIterator,它提供列表的双向遍历和修改功能。

考虑以下示例,我们在遇到Python后将元素JavaScript添加到编程语言列表中:

List<String> programmingLanguages = new ArrayList<>(List.of("Java", "Python", "C++"));
@Test
public void givenList_whenAddElementWithListIterator_thenModifiedList() {
    ListIterator<String> listIterator = programmingLanguages.listIterator();
    while (listIterator.hasNext()) {
        String language = listIterator.next();
        if (language.equals(
"Python")) {
            listIterator.add(
"JavaScript");
        }
    }
    assertIterableEquals(Arrays.asList(
"Java", "Python", "JavaScript", "C++"), programmingLanguages);
}

在提供的代码中,我们初始化一个名为programmingLanguages的列表,其中包含字符串(Java、Python和C++)。此外,我们使用listIterator.next()方法迭代列表的元素。

当我们遇到Python元素时,我们使用listIterator.add(“JavaScript”)动态地在它后面立即插入字符串JavaScript。

最后,测试断言修改后的列表与预期结果匹配,确保在列表中的Python之后成功添加JavaScript 。


让我们将ListIterator方法应用于整数列表,在遇到数字 2 时将值加倍:

List<Integer> numbers = new ArrayList<>(List.of(1, 2, 3));
@Test
public void givenNumericalList_whenMultiplyElementWithListIterator_thenModifiedList() {
    ListIterator<Integer> listIterator = numbers.listIterator();
    while (listIterator.hasNext()) {
        int num = listIterator.next();
        if (num == 2) {
            listIterator.add(num * 10);
        }
    }
    assertIterableEquals(Arrays.asList(1, 2, 20, 3), numbers);
}

在此数字场景中,我们使用ListIterator来迭代整数列表。当遇到数字 2 时,该值会乘以 10 并动态添加到列表中。

2、带副本的增强型 For 循环
另一种策略涉及创建原始列表的副本并在修改原始列表时对其进行迭代。

考虑以下示例,我们将原始列表中每个单词的大写版本添加到列表本身:

@Test
public void givenStringList_whenAddElementWithEnhancedForLoopAndCopy_thenModifiedList() {
    List<String> copyOfWords = new ArrayList<>(programmingLanguages);
    for (String word : copyOfWords) {
        programmingLanguages.add(word.toUpperCase());
    }
    assertIterableEquals(Arrays.asList("Java", "Python", "C++", "JAVA", "PYTHON", "C++"), programmingLanguages);
}

在增强的 for 循环中,我们迭代copyOfWords列表的每个元素,将相应的值转换为大写,并将其添加到原始列表programmingLanguages中。

值得注意的是,此插入过程可确保使用现有单词的大写版本扩展原始列表,同时保持序列完整性。换句话说,programmingLanguages列表将包含原始元素,后跟新添加的大写版本。

现在,让我们将增强的 for 循环方法应用于整数列表,将每个数字乘以 2 相加:

List<Integer> numbers = new ArrayList<>(List.of(1, 2, 3));
@Test
public void givenList_whenAddElementWithEnhancedForLoopAndCopy_thenModifiedList() {
    List<Integer> copyOfNumbers = new ArrayList<>(numbers);
    for (int num : copyOfNumbers) {
        numbers.add(num * 2);
    }
    assertIterableEquals(Arrays.asList(1, 2, 3, 2, 4, 6), numbers);
}

在这里,我们进行迭代,将每个元素乘以 2,并将其添加到原始列表中。与字符串方法相同,

3、利用 Java 8 流方法
Java 8 Streams提供了一种在迭代期间向列表添加元素的简洁方法。

考虑以下示例,我们使用 Java 8 Streams 将字符串JavaScript添加到programmingLanguages列表中:

@Test
public void givenStringList_whenConvertToUpperCaseWithJava8Stream_thenModifiedList() {
    programmingLanguages = programmingLanguages.stream().map(String::toUpperCase).collect(Collectors.toList());
    assertIterableEquals(Arrays.asList("JAVA", "PYTHON", "C++"), programmingLanguages);
}

在此代码片段中,我们利用映射操作,使用toUpperCase方法将列表中的每个字符串元素转换为其等效的大写字母。然后,我们使用Collectors.toList()将转换后的元素收集到一个新列表中。

但是,必须注意的是,每个新元素都会直接更改列表中相应的原始元素。这种直接更改展示了原始列表内容的转换,同时保留了其完整性。

将 Java 8 Stream 方法应用于整数列表,将每个数字乘以 3:

@Test
public void givenNumericalList_whenMultiplyByThreeWithJava8Stream_thenModifiedList() {
    numbers = numbers.stream().map(num -> num * 3).collect(Collectors.toList());
    assertIterableEquals(Arrays.asList(3, 6, 9), numbers);
}

在此测试方法中,我们利用映射操作,列表中的每个数字元素都会经过一次乘以 3 的转换。此外,结果流通过Collectors.toList()收集到一个新列表中。