1. 概述

本文将介绍如何在 Kotlin 中从列表中删除元素,特别是在迭代过程中进行删除操作。Kotlin 提供了多种灵活的方式,可以高效地处理这类需求。我们将通过不同方法来应对不同场景,帮助你选择最适合的方案。

2. 使用 Iterator 删除元素 ✅

首先需要明确的是:只有可变列表(mutable list)才支持删除操作。如果尝试对不可变列表执行删除操作,编译器会抛出异常。因为不可变集合不提供修改方法。

最经典的方式是使用 Iterator,它允许我们在向前遍历过程中安全地删除元素:

@Test
fun `when removing element with Iterator then it works`() {
    val numbers = mutableListOf(1, 2, 3, 4, 5)
    val iterator = numbers.iterator()

    while (iterator.hasNext()) {
        val element = iterator.next()
        if (element % 2 == 0) {
            iterator.remove()
        }
    }
    Assertions.assertThat(numbers).containsExactlyElementsOf(mutableListOf(1, 3, 5))
}

上面的例子中,我们创建了一个可变列表,并通过 iterator 遍历。当满足条件时调用 iterator.remove() 安全地移除当前元素。最终列表中只剩下奇数项(1, 3, 5)。

⚠️ 注意:iterator.remove() 必须在 next() 之后调用,否则会抛出 IllegalStateException

3. 使用 removeAll() 函数删除元素 ✅

Kotlin 提供了 removeAll() 方法,它接收一个谓词(predicate)作为参数,用于定义删除条件。这种方式更加简洁、直观。

示例代码如下:

@Test
fun `when removing element with removeAll function then it works`() {
    val numbers = mutableListOf(1, 2, 3, 4, 5)
    numbers.removeAll { it % 2 == 0 }
    Assertions.assertThat(numbers).containsExactlyElementsOf(mutableListOf(1, 3, 5))
}

如上所示,我们只需要传入一个 lambda 表达式,就能删除所有满足条件的元素。本例中删除了所有偶数项。

⚠️ 注意:removeAll() 会直接修改原列表,并在成功删除元素时返回 true,否则返回 false

4. 遍历时删除元素(倒序遍历)✅

在某些场景下,我们需要根据索引或更复杂的逻辑来删除元素,这时可以考虑手动控制遍历顺序。一个非常重要的技巧是:从后往前遍历(倒序遍历),这样能避免因元素位置变化导致的索引错位问题。

来看一个例子:

@Test
fun `when removing element iterating then it works`() {
    val numbers = mutableListOf(1, 2, 3, 4, 5)
    for (element in numbers.reversed()) {
        if (element % 2 == 0) {
            numbers.remove(element)
        }
    }
    Assertions.assertThat(numbers).containsExactlyElementsOf(mutableListOf(1, 3, 5))
}

我们使用了 reversed() 方法来获取一个倒序的只读列表,然后遍历其中的元素并判断是否删除。这样即使列表在遍历过程中被修改,也不会影响遍历的正确性。

⚠️ 踩坑提醒:如果你尝试正序遍历时调用 remove(),可能会遇到元素跳过或遗漏的问题。

5. 总结

本文我们介绍了在 Kotlin 中迭代列表时安全删除元素的三种常用方式:

方法 特点 使用场景
Iterator.remove() 安全、标准、支持前向遍历 常规删除操作,尤其适合在遍历中按条件删除
removeAll { } 简洁、声明式 条件明确、逻辑简单的批量删除
倒序遍历 + remove() 灵活、可控 删除逻辑依赖索引或复杂判断时

📌 最佳实践建议:

  • 如果只是根据值判断删除,优先使用 removeAll { }
  • 若需在遍历中动态判断并删除,推荐使用 Iterator
  • 若逻辑涉及索引或倒序遍历,使用 reversed() + remove() 是安全的选择

完整示例代码可在 GitHub 上查看。


原始标题:Remove Elements From a List While Iterating in Kotlin