前提知识
kotlin的集合分为可变和不可变,可变的集合带有mutable形容词。
创建方式 | 事例 | 是否可变 | 说明 |
---|---|---|---|
arrayListOf() mutableListOf() | val array = arrayListOf(1,4,7) | 可变 | 必须制定元素类型 |
listOf() | val array = listOf(1,4,7) | 不可变 | 必须制定元素类型,必须指定初始化数据类型 |
arrayMap/SetOf() mutableMap/SetOf() | val array = arrayMapOf(Pair("k","v")) val set = arrayMapOf(1,2,3) | 可变 | 必须使用Pair包装 ,Set集合会去重 |
map/setOf() | val array = map/arraySetOf(Pair("k","v")) | 不可变 | 必须制定元素类型,必须指定初始化数据类型,Set集合会去重 |
转换操作符
list转array,set转list,list转MutableList
val sourceList = mutableListOf(1, 2, 3)
val readOnlyCopyList = sourceList.toList() 转为不可变集合
val sourceList = mutableListOf(1, 2, 3)
val copySet = sourceList.toMutableSet() 转为可变Set
映射操作符
- map
val numbers = setOf(1, 2, 3)
println(numbers.map { it * 3 })
println(numbers.mapIndexed { idx, value -> value * idx })
打印结果
[3, 6, 9]
[0, 2, 6]
- flatMap
val containers = listOf(
listOf("one", "two", "three"),
listOf("four", "five", "six"),
listOf("seven", "eight")
)
println(containers.flatMap { it.values })
//打印 [one, two, three, four, five, six, seven, eight]
过滤操作符
- filter
val numbers = listOf("one", "two", "three", "four")
val longerThan3 = numbers.filter { it.length > 3 }
//打印的结果是 three four
- take
val numbers = listOf("1", "2", "3", "4","5","6")
println(numbers.take(3).toList())
//打印的结果是 1 2 3
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.take(3)) 保留前三个
println(numbers.takeLast(3)) 保留最后三个
//打印
[one, two, three]
[four, five, six]
- drop
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.drop(1)) //删除第一个
println(numbers.dropLast(5)) //删除最后5个
//打印
[two, three, four, five, six]
[one]
- predicates
val numbers = listOf("one", "two", "three", "four")
println(numbers.any { it.endsWith("e") }) //只要有一个以e结尾
println(numbers.none { it.endsWith("a") }) //没有一个以a结尾
println(numbers.all { it.endsWith("e") }) //每一个都是以e结尾
打印结果
true
true
false
- slice
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.slice(1..3)) //位置以1到3进行打算
println(numbers.slice(0..4 step 2)) //0到4 每次价格2个 0,2,2+2
println(numbers.slice(setOf(3, 5, 0)))
打印结果
[two, three, four]
[one, three, five]
[four, six, one]
- find
val numbers = listOf(1, 2, 3, 4)
println(numbers.find { it % 2 == 0 }) 找到能被2 整除的数据
println(numbers.findLast { it % 2 == 0 }) 找到最后一个能被2整除的数
打印
2
4
- suspend(关键字)
用来创建挂起函数(suspendable functions),这些函数允许你在不阻塞当前线程的情况下执行异步操作,标记可以暂停和恢复执行的函数。这些函数只能在协程内部或其他挂起函数中调用
import kotlinx.coroutines.*
// 挂起函数可以暂停执行,等待某些操作完成后再恢复
suspend fun fetchData(): String {
delay(1000) // 模拟网络请求延迟
return "获取到的数据"
}
// 另一个挂起函数,可以调用其他挂起函数
suspend fun processData() {
val data = fetchData()
println("处理数据: $data")
}
fun main() {
// 错误:不能直接在普通函数中调用挂起函数
// val data = fetchData() // 编译错误
// 必须在协程作用域中调用挂起函数
runBlocking {
val data = fetchData()
println(data)
}
}
- runblocking(函数)
Kotlin 协程库中的一个构建器函数,它启动一个新的协程并在该协程中执行给定的挂起函数,然后等待这个协程完成
runBlocking
是一个顶级函数,通常用于测试或者主函数(main)中,当你需要阻塞当前线程直到协程执行完毕
主要用于:
- 测试协程代码
- 作为应用程序的入口点
- 在需要阻塞当前线程等待协程完成的情况下使用
import kotlinx.coroutines.*
fun main() = runBlocking { // 这个协程会在main函数中启动
launch { // 在 runBlocking 的协程中启动一个新的协程
delay(1000L) // 非阻塞地等待 1 秒(延迟)
println("World!") // 在 1 秒后打印
}
println("Hello,") // 协程会在等待时立即打印
}
//输出:
Hello,
World!
runBlocking
创建了一个新的协程,并在其中启动了一个新的协程来执行 delay
函数。runBlocking
会阻塞当前线程直到内部的协程执行完毕
注意事项
- 避免在生产代码中使用 runBlocking:在生产代码中,通常不推荐使用 runBlocking 来阻塞主线程,因为它会导致整个应用程序阻塞。更好的做法是使用 launch 或 async 来启动后台协程,这些函数不会阻塞调用它们的线程。
- 仅在测试或主函数中使用:在测试代码或应用程序的入口点(如 main 函数)中使用 runBlocking 是可以的,因为这些情况下你通常希望等待所有异步操作完成。
- 嵌套使用:尽量避免在 runBlocking 中再次调用 runBlocking,因为这会导致不必要的嵌套和可能的死锁。如果需要嵌套使用,确保内部的 runBlocking 调用不会太长或太复杂。
在生产代码中,更推荐使用 launch
和 async
来启动协程:
fun main() = runBlocking {
launch { // 在 runBlocking 的协程中后台启动一个新的协程
delay(1000L)
println("World!")
}
println("Hello,") // 主协程继续执行
}
launch
用于启动一个后台协程,它不会阻塞 runBlocking
所在的线程。这样,你可以在不阻塞主线程的情况下执行异步操作。如果你需要等待某个异步操作的结果,可以使用 async
fun main() = runBlocking {
val deferred = async {
delay(1000L)
"World!"
}
println("Hello, ${deferred.await()}") // 等待结果并打印
}
async
返回一个 Deferred
对象,你可以使用 await()
方法等待其结果。这种方式允许你以非阻塞的方式获取异步操作的结果