前言
在 Kotlin 里,数组和列表都是用于存储多个元素的数据结构,不过它们在特性和使用场景上存在差异。
介绍
Array(数组)
本质:Kotlin 的 Array 是底层数组的直接包装,与 Java 数组一一对应(如 IntArray 对应 Java 的 int[],Array<Int> 对应 Integer[])。
特性:
- 长度固定:创建时必须指定大小,且不可动态扩容 / 缩容。
- 可修改元素:通过索引
[]可以修改元素(array[0] = 1),但不能改变数组长度。 - 支持基本类型优化:如
IntArray、DoubleArray等避免了装箱拆箱,性能更好。
适用场景:需要固定长度的连续内存存储,或与 Java 数组交互时。
示例:
1 | val array = arrayOf(1, 2, 3) // 长度为3的Array<Int> |
Collection
Collection 是一个接口,它代表一组元素,但它本身并没有直接提供取值的方法。
这是因为 Collection 是一个通用的抽象概念,它只定义了集合的基本操作,例如检查集合的大小、判断元素是否存在等。
不过,Collection 有两个重要的子接口 List 和 Set,它们提供了不同的取值方式。
1 | public interface Collection<out E> : Iterable<E> { |
List(只读列表接口)
本质:Kotlin 标准库中的只读列表接口,继承自 Collection,定义了列表的查询操作。
特性:
- 不可修改:仅支持查询(
get(index)、size、contains()等),无add、remove等修改方法。 - 长度可变(间接):若底层是可变列表(如
ArrayList),通过原可变列表修改时,List视图会同步变化(但不能直接通过List接口修改)。 - 无固定实现:
List是接口,具体实现由ArrayList、LinkedList等提供。
适用场景:仅需读取数据,或作为不可变数据传递(避免外部修改)。
示例:
1 | val list: List<Int> = listOf(1, 2, 3) |
修改
1 | val selectIndexList: List<Int> = listOf(1, 2, 3) |
MutableList(可变列表接口)
本质:继承自 List 的子接口,新增了修改元素的方法。
特性:
- 可修改:支持
add()、remove()、set()等操作,可动态改变元素和长度。 - 无固定实现:需通过具体实现类(如
ArrayList)实例化。
与 List 的关系:MutableList 是 List 的子类型,即 MutableList 可以赋值给 List 变量(但反之不行)。
示例:
1 | val mutableList: MutableList<Int> = mutableListOf(1, 2, 3) |
ArrayList(动态数组实现类)
本质:MutableList 接口的具体实现类,基于动态数组(可自动扩容的数组)实现。
特性:
- 实现
MutableList:支持所有增删改查操作。 - 动态扩容:当元素数量超过当前容量时,会自动创建更大的数组并复制元素。
- 随机访问高效:通过索引
get(index)访问元素的时间复杂度为 O (1),但中间插入 / 删除元素效率低(需移动后续元素)。
与 mutableListOf() 的关系:mutableListOf() 默认返回 ArrayList 实例(除非指定其他实现)。
示例:
1 | val arrayList = arrayListOf(1, 2, 3) // 直接创建ArrayList |
对比与关联
对比
| 类型 | 性质 | 可修改性 | 长度是否固定 | 典型实现 / 特点 | 适用场景 |
|---|---|---|---|---|---|
Array |
数组(类) | 可修改元素 | 固定 | 连续内存,基本类型优化 | 固定长度场景,与 Java 数组交互 |
List |
只读接口 | 不可修改 | 不固定(视图) | 无具体实现,依赖底层容器 | 仅查询数据,传递不可变数据 |
MutableList |
可变接口 | 可修改(增删改) | 不固定 | 定义修改方法,无具体实现 | 需要动态修改元素的场景(抽象接口) |
ArrayList |
实现类 | 可修改(增删改) | 不固定 | 动态数组,随机访问高效 | 频繁查询,较少中间插入 / 删除的动态列表场景 |
关键关联
ArrayList是MutableList的实现类,mutableListOf()默认返回ArrayList。List可以是ArrayList的只读视图(通过asList()转换)。Array是底层数据结构,而List/MutableList是更高层次的集合接口,提供更丰富的操作(如forEach、filter等)。
实际开发中,优先使用 listOf()(只读)和 mutableListOf()(可变),仅在需要数组特性(如固定长度、基本类型优化)时使用 Array。
示例
不可变长
Array和List
1 | val arr0: Array<String> = arrayOf("A", "B") |
可变长
ArrayList 和 MutableList
1 | val list30: ArrayList<String> = arrayListOf("A", "B") |
字符串分割
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 | val original = arrayOf(1, 2, 3, 4, 5) |
这个是前后都包含
1 | val useList = optList.sliceArray(0..optNum - 1) |
使用copyOfRange
对于原生类型数组(如 IntArray、DoubleArray 等),同样适用上述方法:
1 | val numbers = intArrayOf(10, 20, 30, 40, 50) |
这个是不包含最后
1 | val useList = optList.copyOfRange(0, optNum) |