1. 简介

在 Kotlin 中,ArrayList 是一种常用的数据结构,用于存储元素集合。在实际开发中,我们有时需要移除 ArrayList 的第一个元素。

本文将介绍几种实现该操作的方法,并结合代码示例说明各自的使用场景和注意事项,帮助你在不同情境下选择最合适的方案。

2. 使用 removeAt()

removeAt()ArrayList 提供的直接方法,用于根据索引删除指定位置的元素。✅ 要删除第一个元素,只需传入索引 0 即可。

@Test
fun `Remove first element using removeAt`() {
    val arrayList = arrayListOf("Apple", "Banana", "Cherry")

    arrayList.removeAt(0)

    assertEquals(listOf("Banana", "Cherry"), arrayList)
}

⚠️ 注意:此方法会直接修改原列表,适用于允许原数据被改变的场景。如果后续还需要使用原始列表,需提前备份。

3. 使用 remove()

remove(element) 方法用于删除列表中第一次出现的指定元素。要删除首元素,前提是你知道它的值。

@Test
fun `Remove first element using remove`() {
    val arrayList = arrayListOf("Apple", "Banana", "Cherry")

    arrayList.remove("Apple")

    assertEquals(listOf("Banana", "Cherry"), arrayList)
}

❌ 缺点很明显:必须明确知道首元素的值,且若该值在列表中重复出现,只会删第一个匹配项——虽然这正好是我们想要的行为,但语义上不够清晰,容易引发误解。

3.1 结合 first() 使用 remove()

为了动态获取首元素并删除,可以结合 first() 函数:

@Test
fun `Remove first element using remove and first`() {
    val arrayList = arrayListOf("Apple", "Banana", "Cherry")

    arrayList.remove(arrayList.first())

    assertEquals(listOf("Banana", "Cherry"), arrayList)
}

⚠️ 踩坑提醒:如果列表为空,调用 first() 会抛出 NoSuchElementException。生产环境务必先判空或使用 firstOrNull() 配合安全调用。

4. 使用 subList() 创建新列表

subList(fromIndex, toIndex) 可截取原列表的一部分,返回一个视图(view)。通过从索引 1 开始截取,即可排除第一个元素:

@Test
fun `Remove first element by creating a sublist`() {
    val arrayList = arrayListOf("Apple", "Banana", "Cherry")

    val updatedList = arrayList.subList(1, arrayList.size)

    assertEquals(listOf("Banana", "Cherry"), updatedList)
}

⚠️ 关键警告:subList() 返回的是原列表的视图,不是独立副本。这意味着对 updatedList 的修改会影响原 arrayList,反之亦然。这种“隐式联动”极易踩坑,除非你明确需要这种行为,否则不推荐直接使用。

5. 使用 slice()

slice() 提供了一种更安全的方式,可以从指定索引范围提取元素并生成全新的列表实例

@Test
fun `Remove first element by using slice`() {
    val arrayList = arrayListOf("Apple", "Banana", "Cherry")
    val updatedList = arrayList.slice(1 until arrayList.size)

    assertEquals(listOf("Banana", "Cherry"), updatedList)
}

✅ 推荐场景:

  • 需要不可变结果
  • 希望避免与原列表产生副作用
  • 对性能要求不高(毕竟多了一次拷贝)

subList() 相比,slice() 更符合“函数式”编程习惯,结果可预期。

6. 使用 drop()

drop(n) 是标准库中非常简洁的方法,用于跳过前 n 个元素,返回剩余部分组成的新列表。

@Test
fun `Remove first element by using drop`() {
    val arrayList = arrayListOf("Apple", "Banana", "Cherry")

    val updatedList = arrayList.drop(1)

    assertEquals(listOf("Banana", "Cherry"), updatedList)
}

✅ 特点总结:

  • 语义清晰:“丢掉第一个”
  • 返回新列表,不影响原数据
  • 支持链式调用,适合流式处理
  • 是函数式风格中的常用操作

这是大多数情况下推荐的选择,尤其在配合 mapfilter 等操作时表现自然。

7. 使用 filterIndexed()

filterIndexed() 允许你在过滤时访问元素的索引,因此可以通过判断索引是否为 0 来排除首元素:

@Test
fun `Remove first element by using filterIndexed`() {
    val arrayList = arrayListOf("Apple", "Banana", "Cherry")

    val updatedList = arrayList.filterIndexed { index, _ -> index != 0 }

    assertEquals(listOf("Banana", "Cherry"), updatedList)
}

✅ 优势:

  • 灵活性高,可扩展为“删除前 N 个”等复杂逻辑
  • 易于理解,条件明确

❌ 劣势:

  • 性能略低于 drop(),因为遍历了所有元素
  • 对简单需求来说略显“重”

仅建议在需要结合索引做复杂判断时使用。

8. 结论

本文介绍了 Kotlin 中移除 ArrayList 第一个元素的多种方式,各有适用场景:

方法 是否修改原列表 是否返回新列表 推荐程度
removeAt(0) ✅ 是 ❌ 否 ⭐⭐⭐⭐☆(适合就地修改)
remove(first()) ✅ 是 ❌ 否 ⭐⭐☆☆☆(注意空列表异常)
subList(1, size) ⚠️ 视图联动 ❌ 否 ⭐☆☆☆☆(易踩坑,慎用)
slice(1..last) ❌ 否 ✅ 是 ⭐⭐⭐☆☆(安全但稍重)
drop(1) ❌ 否 ✅ 是 ⭐⭐⭐⭐⭐(首选函数式方案)
filterIndexed ❌ 否 ✅ 是 ⭐⭐⭐☆☆(灵活但性能一般)

最佳实践建议

  • 若允许修改原列表 → 使用 removeAt(0)
  • 若需保留原列表 → 使用 drop(1)
  • 避免使用 subList() 处理可变数据,防止副作用

示例代码已托管至 GitHub:https://github.com/Baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-collections-list


原始标题:Removing the First Element From an ArrayList in Kotlin