集合
在编程时,能够将数据分组到结构中以便后续处理是非常有用的。Kotlin 提供的集合正是为了这一目的。
Kotlin 拥有以下用于对项进行分组的集合类型:
| 集合类型 | 描述 |
|---|---|
| List | 有序的项集合 |
| Set | 唯一的无序项集合 |
| Map | 键值对的集合,其中键是唯一的,且仅映射到一个值 |
每种集合类型都可以是可变的或只读的。
List
List 按添加顺序存储项,并允许重复项。
要创建只读 List (List),请使用 listOf() 函数。
要创建可变 List (MutableList), 请使用 mutableListOf() 函数。
创建 List 时,Kotlin 可以推断存储的项类型。要显式声明类型,请在 List 声明后的尖括号 <> 内添加类型:
fun main() {
// 只读 List
val readOnlyShapes = listOf("triangle", "square", "circle")
println(readOnlyShapes)
// [triangle, square, circle]
// 带有显式类型声明的可变 List
val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
println(shapes)
// [triangle, square, circle]
}为了防止不必要的修改,你可以通过将可变 List 赋值给一个
List来创建该 List 的只读视图:kotlinval shapes: MutableList<String> = mutableListOf("triangle", "square", "circle") val shapesLocked: List<String> = shapes这也称为转换。
List 是有序的,因此要访问 List 中的项,请使用索引访问运算符 []:
fun main() {
val readOnlyShapes = listOf("triangle", "square", "circle")
println("The first item in the list is: ${readOnlyShapes[0]}")
// The first item in the list is: triangle
}要获取 List 中的第一个或最后一个项,请分别使用 .first() 和 .last() 函数:
fun main() {
val readOnlyShapes = listOf("triangle", "square", "circle")
println("The first item in the list is: ${readOnlyShapes.first()}")
// The first item in the list is: triangle
}
.first()和.last()函数是扩展函数的示例。要在对象上调用扩展函数,请在对象后紧跟一个点号.并写下函数名称。扩展函数将在中级教程中详细介绍。 目前,你只需要知道如何调用它们即可。
要获取 List 中的项数,请使用 .count() 函数:
fun main() {
val readOnlyShapes = listOf("triangle", "square", "circle")
println("This list has ${readOnlyShapes.count()} items")
// This list has 3 items
}要检查某个项是否在 List 中,请使用 in 运算符:
fun main() {
val readOnlyShapes = listOf("triangle", "square", "circle")
println("circle" in readOnlyShapes)
// true
}要从可变 List 中添加或移除项,请分别使用 .add() 和 .remove() 函数:
fun main() {
val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
// 将 "pentagon" 添加到 List 中
shapes.add("pentagon")
println(shapes)
// [triangle, square, circle, pentagon]
// 从 List 中移除第一个 "pentagon"
shapes.remove("pentagon")
println(shapes)
// [triangle, square, circle]
}Set
List 是有序且允许重复项的,而 Set 则是无序且仅存储唯一项的。
要创建只读 Set (Set),请使用 setOf() 函数。
要创建可变 Set (MutableSet), 请使用 mutableSetOf() 函数。
创建 Set 时,Kotlin 可以推断存储的项类型。要显式声明类型,请在 Set 声明后的尖括号 <> 内添加类型:
fun main() {
// 只读 Set
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
// 带有显式类型声明的可变 Set
val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")
println(readOnlyFruit)
// [apple, banana, cherry]
}你可以在前面的示例中看到,由于 Set 仅包含唯一元素,重复的 "cherry" 项被丢弃了。
为了防止不必要的修改,你可以通过将可变 Set 赋值给一个
Set来创建该 Set 的只读视图:kotlinval fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry") val fruitLocked: Set<String> = fruit
由于 Set 是无序的,你无法访问特定索引处的项。
要获取 Set 中的项数,请使用 .count() 函数:
fun main() {
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
println("This set has ${readOnlyFruit.count()} items")
// This set has 3 items
}要检查某个项是否在 Set 中,请使用 in 运算符:
fun main() {
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
println("banana" in readOnlyFruit)
// true
}要从可变 Set 中添加或移除项,请分别使用 .add() 和 .remove() 函数:
fun main() {
val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")
fruit.add("dragonfruit") // 将 "dragonfruit" 添加到 Set
println(fruit) // [apple, banana, cherry, dragonfruit]
fruit.remove("dragonfruit") // 从 Set 中移除 "dragonfruit"
println(fruit) // [apple, banana, cherry]
}Map
Map 以键值对的形式存储项。你可以通过引用键来访问值。你可以将 Map 想象成一份食物菜单。 你可以通过找到你想吃的食物(键)来找到价格(值)。如果你想在不使用数字索引(如 List)的情况下查找值,Map 非常有用。
- Map 中的每个键都必须是唯一的,以便 Kotlin 能够理解你想要获取哪个值。
- 你在 Map 中可以有重复的值。
要创建只读 Map (Map),请使用 mapOf() 函数。
要创建可变 Map (MutableMap), 请使用 mutableMapOf() 函数。
创建 Map 时,Kotlin 可以推断存储的项类型。要显式声明类型,请在 Map 声明后的尖括号 <> 内添加键和值的类型。例如:MutableMap<String, Int>。 键的类型为 String,值的类型为 Int。
创建 Map 最简单的方法是在每个键与其相关值之间使用 to:
fun main() {
// 只读 Map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu)
// {apple=100, kiwi=190, orange=100}
// 带有显式类型声明的可变 Map
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(juiceMenu)
// {apple=100, kiwi=190, orange=100}
}为了防止不必要的修改,你可以通过将可变 Map 赋值给一个
Map来创建该 Map 的只读视图:kotlinval juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100) val juiceMenuLocked: Map<String, Int> = juiceMenu
要访问 Map 中的值,请使用索引访问运算符 [] 及其键:
fun main() {
// 只读 Map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("The value of apple juice is: ${readOnlyJuiceMenu["apple"]}")
// The value of apple juice is: 100
}如果你尝试使用 Map 中不存在的键来访问键值对,你将看到一个
null值:kotlinfun main() { // 只读 Map val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100) println("The value of pineapple juice is: ${readOnlyJuiceMenu["pineapple"]}") // The value of pineapple juice is: null }本教程稍后将在 null 安全章节中解释 null 值。
你还可以使用索引访问运算符 [] 向可变 Map 添加项:
fun main() {
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
juiceMenu["coconut"] = 150 // 向 Map 中添加键 "coconut" 及其值 150
println(juiceMenu)
// {apple=100, kiwi=190, orange=100, coconut=150}
}要从可变 Map 中移除项,请使用 .remove() 函数:
fun main() {
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
juiceMenu.remove("orange") // 从 Map 中移除键 "orange"
println(juiceMenu)
// {apple=100, kiwi=190}
}要获取 Map 中的项数,请使用 .count() 函数:
fun main() {
// 只读 Map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("This map has ${readOnlyJuiceMenu.count()} key-value pairs")
// This map has 3 key-value pairs
}要检查某个特定键是否已包含在 Map 中,请使用 .containsKey() 函数:
fun main() {
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu.containsKey("kiwi"))
// true
}要获取 Map 的键或值的集合,请分别使用 keys 和 values 属性:
fun main() {
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu.keys)
// [apple, kiwi, orange]
println(readOnlyJuiceMenu.values)
// [100, 190, 100]
}
keys和values是对象属性的示例。要访问对象的属性,请在对象后紧跟一个点号.并写下属性名称。属性将在类章节中进行更详细的讨论。 在本教程的此阶段,你只需要知道如何访问它们即可。
要检查键或值是否在 Map 中,请使用 in 运算符:
fun main() {
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("orange" in readOnlyJuiceMenu.keys)
// true
// 或者,你不需要使用 keys 属性
println("orange" in readOnlyJuiceMenu)
// true
println(200 in readOnlyJuiceMenu.values)
// false
}有关集合用法的更多信息,请参阅集合。
现在你已经了解了基本类型以及如何管理集合,是时候探索可以在程序中使用的控制流了。
练习
练习 1
你有一个“绿色”数字列表和一个“红色”数字列表。完成代码以打印总共有多少个数字。
fun main() {
val greenNumbers = listOf(1, 4, 23)
val redNumbers = listOf(17, 2)
// 在此处编写你的代码
}示例解法
fun main() {
val greenNumbers = listOf(1, 4, 23)
val redNumbers = listOf(17, 2)
val totalCount = greenNumbers.count() + redNumbers.count()
println(totalCount)
}练习 2
你有一组服务器支持的协议。用户请求使用特定协议。完成程序以检查请求的协议是否受支持(isSupported 必须是一个布尔值)。
fun main() {
val SUPPORTED = setOf("HTTP", "HTTPS", "FTP")
val requested = "smtp"
val isSupported = // 在此处编写你的代码
println("Support for $requested: $isSupported")
}示例解法
fun main() {
val SUPPORTED = setOf("HTTP", "HTTPS", "FTP")
val requested = "smtp"
val isSupported = requested.uppercase() in SUPPORTED
println("Support for $requested: $isSupported")
}练习 3
定义一个 Map,将 1 到 3 的整数与其对应的拼写形式关联起来。使用此 Map 拼写给定的数字。
fun main() {
val number2word = // 在此处编写你的代码
val n = 2
println("$n is spelled as '${<在此处编写你的代码 >}'")
}示例解法
fun main() {
val number2word = mapOf(1 to "one", 2 to "two", 3 to "three")
val n = 2
println("$n is spelt as '${number2word[n]}'")
}