Kotlin中数组和列表的操作

前言

在 Kotlin 里,数组和列表都是用于存储多个元素的数据结构,不过它们在特性和使用场景上存在差异。

介绍

Array(数组)

本质:Kotlin 的 Array 是底层数组的直接包装,与 Java 数组一一对应(如 IntArray 对应 Java 的 int[]Array<Int> 对应 Integer[])。

特性:

  • 长度固定:创建时必须指定大小,且不可动态扩容 / 缩容。
  • 可修改元素:通过索引 [] 可以修改元素(array[0] = 1),但不能改变数组长度。
  • 支持基本类型优化:如 IntArrayDoubleArray 等避免了装箱拆箱,性能更好。

适用场景:需要固定长度的连续内存存储,或与 Java 数组交互时。

示例:

1
2
3
val array = arrayOf(1, 2, 3) // 长度为3的Array<Int>
array[0] = 0 // 允许修改元素
// array.add(4) 编译错误,无法改变长度

Collection

Collection 是一个接口,它代表一组元素,但它本身并没有直接提供取值的方法。

这是因为 Collection 是一个通用的抽象概念,它只定义了集合的基本操作,例如检查集合的大小、判断元素是否存在等。

不过,Collection 有两个重要的子接口 ListSet,它们提供了不同的取值方式。

1
2
3
4
5
6
7
public interface Collection<out E> : Iterable<E> {
public val size: Int
public fun isEmpty(): Boolean
public operator fun contains(element: @UnsafeVariance E): Boolean
override fun iterator(): Iterator<E>
public fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean
}

List(只读列表接口)

本质:Kotlin 标准库中的只读列表接口,继承自 Collection,定义了列表的查询操作。

特性

  • 不可修改:仅支持查询(get(index)sizecontains() 等),无 addremove 等修改方法。
  • 长度可变(间接):若底层是可变列表(如 ArrayList),通过原可变列表修改时,List 视图会同步变化(但不能直接通过 List 接口修改)。
  • 无固定实现:List 是接口,具体实现由 ArrayListLinkedList 等提供。

适用场景:仅需读取数据,或作为不可变数据传递(避免外部修改)。

示例:

1
2
3
val list: List<Int> = listOf(1, 2, 3)
println(list[0]) // 允许查询
// list.add(4) 编译错误,不支持修改

修改

1
2
3
4
val selectIndexList: List<Int> = listOf(1, 2, 3)                       
val tempList = selectIndexList.toMutableList()
tempList.add(4)
itemClick(tempList.toList())

MutableList(可变列表接口)

本质:继承自 List 的子接口,新增了修改元素的方法。

特性

  • 可修改:支持 add()remove()set() 等操作,可动态改变元素和长度。
  • 无固定实现:需通过具体实现类(如 ArrayList)实例化。

List 的关系MutableListList 的子类型,即 MutableList 可以赋值给 List 变量(但反之不行)。

示例

1
2
3
val mutableList: MutableList<Int> = mutableListOf(1, 2, 3)
mutableList.add(4) // 允许修改
val list: List<Int> = mutableList // 可变列表可转为只读视图

ArrayList(动态数组实现类)

本质MutableList 接口的具体实现类,基于动态数组(可自动扩容的数组)实现。

特性:

  • 实现 MutableList:支持所有增删改查操作。
  • 动态扩容:当元素数量超过当前容量时,会自动创建更大的数组并复制元素。
  • 随机访问高效:通过索引 get(index) 访问元素的时间复杂度为 O (1),但中间插入 / 删除元素效率低(需移动后续元素)。

mutableListOf() 的关系mutableListOf() 默认返回 ArrayList 实例(除非指定其他实现)。

示例:

1
2
val arrayList = arrayListOf(1, 2, 3) // 直接创建ArrayList
val mutableList: MutableList<Int> = mutableListOf(1, 2, 3) // 实际也是ArrayList

对比与关联

对比

类型 性质 可修改性 长度是否固定 典型实现 / 特点 适用场景
Array 数组(类) 可修改元素 固定 连续内存,基本类型优化 固定长度场景,与 Java 数组交互
List 只读接口 不可修改 不固定(视图) 无具体实现,依赖底层容器 仅查询数据,传递不可变数据
MutableList 可变接口 可修改(增删改) 不固定 定义修改方法,无具体实现 需要动态修改元素的场景(抽象接口)
ArrayList 实现类 可修改(增删改) 不固定 动态数组,随机访问高效 频繁查询,较少中间插入 / 删除的动态列表场景

关键关联

  • ArrayListMutableList 的实现类,mutableListOf() 默认返回 ArrayList
  • List 可以是 ArrayList 的只读视图(通过 asList() 转换)。
  • Array 是底层数据结构,而 List/MutableList 是更高层次的集合接口,提供更丰富的操作(如 forEachfilter 等)。

实际开发中,优先使用 listOf()(只读)和 mutableListOf()(可变),仅在需要数组特性(如固定长度、基本类型优化)时使用 Array

示例

不可变长

Array和List

1
2
3
4
5
6
val arr0: Array<String> = arrayOf("A", "B")
val arr1: Array<String> = mutableListOf<String>("A", "B").toTypedArray()


val list0: List<String> = listOf<String>("A")
val list1: List<String> = mutableListOf<String>("A", "B").toList()

可变长

ArrayList 和 MutableList

1
2
3
4
val list30: ArrayList<String> = arrayListOf("A", "B")
list30.add("C")
val list31: MutableList<String> = mutableListOf<String>("A", "B")
list31.add("C")

字符串分割

1
val nameList = "张三;李四;王五".split(';')

注意

split操作返回的是List。

List转Array

1
val nameArr = "张三;李四;王五".split(';').toTypedArray()

map

1
val optList = "ABCDEFGHIJKLMN".map { it + "" }.toTypedArray()

注意

map操作返回的是List。

子数组

使用sliceArray

1
2
3
4
5
val original = arrayOf(1, 2, 3, 4, 5)
// 可以传入一个索引范围
val subArray1 = original.sliceArray(1..3) // 结果为 [2, 3, 4]
// 也可以传入索引列表
val subArray2 = original.sliceArray(listOf(0, 2, 4)) // 结果为 [1, 3, 5]

这个是前后都包含

1
val useList = optList.sliceArray(0..optNum - 1)

使用copyOfRange

对于原生类型数组(如 IntArray、DoubleArray 等),同样适用上述方法:

1
2
val numbers = intArrayOf(10, 20, 30, 40, 50)
val subNumbers = numbers.copyOfRange(2, 4) // 结果为 [30, 40]

这个是不包含最后

1
val useList = optList.copyOfRange(0, optNum)