3.2.3 集合
原文链接: https://kotlinlang.org/docs/kotlin-tour-collections.html
3.2.3 集合
编程时,能够把数据分组到某种结构中以便后续处理是很有用的。Kotlin 提供的集合正是为此而生。
Kotlin 提供了以下用于把项目分组的集合:
| 集合类型 | 说明 |
| Lists | 有序的项目集合 |
| Sets | 只包含唯一项目的无序集合 |
| Maps | 键值对集合,其中键是唯一的,并且只映射到一个值 |
每种集合类型都可以是可变的或只读的。
List
列表按项目添加的顺序存储它们,并允许出现重复的项目。
要创建只读列表(List),请使用 listOf() 函数。
要创建可变列表(MutableList),请使用 mutableListOf() 函数。
创建列表时,Kotlin 可以推断所存储项目的类型。要显式声明类型,请在列表声明之后、尖括号 <> 内写上该类型:
1
2
3
4
5
6
7
8
9
10
11
| fun main() {
// Read only list
val readOnlyShapes = listOf("triangle", "square", "circle")
println(readOnlyShapes)
// [triangle, square, circle]
// Mutable list with explicit type declaration
val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
println(shapes)
// [triangle, square, circle]
}
|
提示: 为防止不必要的修改,你可以把可变列表赋值给一个 List,从而创建它的只读视图:kotlin val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle") val shapesLocked: List<String> = shapes 这也称为类型转换。
列表是有序的,因此要访问列表中的某个项目,请使用索引访问运算符 []:
1
2
3
4
5
| 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
}
|
要获取列表中的第一个或最后一个项目,请分别使用 .first() 和 .last() 函数:
1
2
3
4
5
| 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() 函数是扩展函数的例子。要在对象上调用扩展函数,请把函数名写在对象之后,并用句点 . 连接。扩展函数在进阶导览中有详细讲解。现在你只需要知道如何调用它们。
要获取列表中项目的数量,请使用 .count() 函数:
1
2
3
4
5
| fun main() {
val readOnlyShapes = listOf("triangle", "square", "circle")
println("This list has ${readOnlyShapes.count()} items")
// This list has 3 items
}
|
要检查某个项目是否在列表中,请使用 in 运算符:
1
2
3
4
5
| fun main() {
val readOnlyShapes = listOf("triangle", "square", "circle")
println("circle" in readOnlyShapes)
// true
}
|
要在可变列表中添加或移除项目,请分别使用 .add() 和 .remove() 函数:
1
2
3
4
5
6
7
8
9
10
11
12
| fun main() {
val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
// Add "pentagon" to the list
shapes.add("pentagon")
println(shapes)
// [triangle, square, circle, pentagon]
// Remove the first "pentagon" from the list
shapes.remove("pentagon")
println(shapes)
// [triangle, square, circle]
}
|
Set
列表是有序的并允许重复项目,而集(set)是无序的,并且只存储唯一项目。
要创建只读集(Set),请使用 setOf() 函数。
要创建可变集(MutableSet),请使用 mutableSetOf() 函数。
创建集时,Kotlin 可以推断所存储项目的类型。要显式声明类型,请在集声明之后、尖括号 <> 内写上该类型:
1
2
3
4
5
6
7
8
9
| fun main() {
// Read-only set
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
// Mutable set with explicit type declaration
val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")
println(readOnlyFruit)
// [apple, banana, cherry]
}
|
从上面的示例可以看到,由于集只包含唯一元素,重复的 "cherry" 项目被丢弃了。
提示: 为防止不必要的修改,你可以把可变集赋值给一个 Set,从而创建它的只读视图:kotlin val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry") val fruitLocked: Set<String> = fruit
注意: 由于集是无序的,你无法访问特定索引处的项目。
要获取集中项目的数量,请使用 .count() 函数:
1
2
3
4
5
| fun main() {
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
println("This set has ${readOnlyFruit.count()} items")
// This set has 3 items
}
|
要检查某个项目是否在集中,请使用 in 运算符:
1
2
3
4
5
| fun main() {
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
println("banana" in readOnlyFruit)
// true
}
|
要在可变集中添加或移除项目,请分别使用 .add() 和 .remove() 函数:
1
2
3
4
5
6
7
8
| fun main() {
val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")
fruit.add("dragonfruit") // Add "dragonfruit" to the set
println(fruit) // [apple, banana, cherry, dragonfruit]
fruit.remove("dragonfruit") // Remove "dragonfruit" from the set
println(fruit) // [apple, banana, cherry]
}
|
Map
映射(map)以键值对的形式存储项目。你通过引用键来访问值。可以把映射想象成一份菜单:只要找到你想吃的食物(键),就能查到它的价格(值)。当你想在不使用列表那种数字索引的情况下查找某个值时,映射非常有用。
注意: * 映射中的每个键都必须是唯一的,这样 Kotlin 才能理解你想获取哪个值。 * 映射中可以出现重复的值。
要创建只读映射(Map),请使用 mapOf() 函数。
要创建可变映射(MutableMap),请使用 mutableMapOf() 函数。
创建映射时,Kotlin 可以推断所存储项目的类型。要显式声明类型,请在映射声明之后、尖括号 <> 内写上键和值的类型。例如:MutableMap<String, Int>。键的类型是 String,值的类型是 Int。
创建映射最简单的方式是在每个键与其对应的值之间使用 to:
1
2
3
4
5
6
7
8
9
10
11
| fun main() {
// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu)
// {apple=100, kiwi=190, orange=100}
// Mutable map with explicit type declaration
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(juiceMenu)
// {apple=100, kiwi=190, orange=100}
}
|
提示: 为防止不必要的修改,你可以把可变映射赋值给一个 Map,从而创建它的只读视图:kotlin val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100) val juiceMenuLocked: Map<String, Int> = juiceMenu
要访问映射中的某个值,请用它的键配合索引访问运算符 []:
1
2
3
4
5
6
| fun main() {
// Read-only 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
}
|
注意: 如果你用一个映射中不存在的键去访问键值对,会看到 null 值:kotlin fun main() { //sampleStart // Read-only 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 //sampleEnd } {kotlin-runnable=“true” kotlin-min-compiler-version=“1.3” id=“kotlin-tour-map-no-key” validate=“false”} 本次导览会在后面的空安全一章中讲解 null 值。
你也可以用索引访问运算符 [] 向可变映射中添加项目:
1
2
3
4
5
6
| fun main() {
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
juiceMenu["coconut"] = 150 // Add key "coconut" with value 150 to the map
println(juiceMenu)
// {apple=100, kiwi=190, orange=100, coconut=150}
}
|
要从可变映射中移除项目,请使用 .remove() 函数:
1
2
3
4
5
6
| fun main() {
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
juiceMenu.remove("orange") // Remove key "orange" from the map
println(juiceMenu)
// {apple=100, kiwi=190}
}
|
要获取映射中项目的数量,请使用 .count() 函数:
1
2
3
4
5
6
| fun main() {
// Read-only 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
}
|
要检查某个键是否已经包含在映射中,请使用 .containsKey() 函数:
1
2
3
4
5
| fun main() {
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu.containsKey("kiwi"))
// true
}
|
要获取映射的键集合或值集合,请分别使用 keys 和 values 属性:
1
2
3
4
5
6
7
| 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 是对象属性的例子。要访问对象的属性,请把属性名写在对象之后,并用句点 . 连接。属性会在类一章中详细讨论。在导览的这一阶段,你只需要知道如何访问它们。
要检查某个键或值是否在映射中,请使用 in 运算符:
1
2
3
4
5
6
7
8
9
10
11
12
| fun main() {
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("orange" in readOnlyJuiceMenu.keys)
// true
// Alternatively, you don't need to use the keys property
println("orange" in readOnlyJuiceMenu)
// true
println(200 in readOnlyJuiceMenu.values)
// false
}
|
关于可以对集合做些什么的更多信息,请参阅集合。
现在你已经了解了基本类型以及如何管理集合,接下来该探索可以在程序中使用的控制流了。
练习
习题 1
你有一个「绿色」数字列表和一个「红色」数字列表。请补全代码,打印出总共有多少个数字。
1
2
3
4
5
| fun main() {
val greenNumbers = listOf(1, 4, 23)
val redNumbers = listOf(17, 2)
// Write your code here
}
|
1
2
3
4
5
6
| fun main() {
val greenNumbers = listOf(1, 4, 23)
val redNumbers = listOf(17, 2)
val totalCount = greenNumbers.count() + redNumbers.count()
println(totalCount)
}
|
示例解答
习题 2
你有一个服务器支持的协议集。用户请求使用某个特定的协议。请补全程序,检查所请求的协议是否受支持(isSupported 必须是布尔值)。
1
2
3
4
5
6
| fun main() {
val SUPPORTED = setOf("HTTP", "HTTPS", "FTP")
val requested = "smtp"
val isSupported = // Write your code here
println("Support for $requested: $isSupported")
}
|
提示
请确保以大写形式检查所请求的协议。你可以借助 .uppercase() 函数来完成。
1
2
3
4
5
6
| fun main() {
val SUPPORTED = setOf("HTTP", "HTTPS", "FTP")
val requested = "smtp"
val isSupported = requested.uppercase() in SUPPORTED
println("Support for $requested: $isSupported")
}
|
示例解答
习题 3
定义一个映射,把 1 到 3 的整数与它们对应的英文拼写关联起来。用这个映射拼出给定的数字。
1
2
3
4
5
| fun main() {
val number2word = // Write your code here
val n = 2
println("$n is spelled as '${<Write your code here >}'")
}
|
1
2
3
4
5
| fun main() {
val number2word = mapOf(1 to "one", 2 to "two", 3 to "three")
val n = 2
println("$n is spelled as '${number2word[n]}'")
}
|
示例解答
另请参阅
上一步
下一步