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 上查看。