一、Kotlin的作用域函数
- run {…}
- with(T){…}
- let{…}
- apply{…}
- also{…}
作用域函数是Kotlin内置的一系列可以对数据做一些变换的函数,与集合的操作符很相似,但集合的操作符只能作用域集合对象,而作用域函数可以操作任何对象。
二、代码实现
package zyf.kotlin
fun main(args: Array<String>) {
val user = User("zyf")
/**
* let与run都会返回闭包的执行结果
* 不同:
* let有闭包参数,run没有闭包参数
* let的闭包参数就是调用者本身,参数名为it
* run没有闭包参数,可以使用this指代调用者
* 注:在let中,不可以使用this指代调用者
*/
val letResult = user.let {
"let::${it.javaClass}"
}
println(letResult)
val runResult = user.run {
"run::${this.javaClass}"
}
println(runResult)
/**
* also与apply都不返回闭包的执行结果
* also和apply都会返回调用者本身,所以可以使用链式调用
* 不同:
* also有闭包参数,apply没有闭包参数
* it与this的区别与let,run类似
*/
user.also {
println("also::${it.javaClass}")
}
user.apply {
println("apply::${this.javaClass}")
}
/**
* takeIf的闭包会返回一个判断结果,为false时,takeIf函数会返回空
* 如果判断为true,则会返回调用者本身,可以继续链式调用
* takeUnless 与 takeIf刚好相反,闭包的判断结果,为true时函数会返回空
*
*/
user.takeIf {
it.name.isNotEmpty()
}?.also {
println("姓名为${it.name}")
}?: println("姓名为空")
user.takeUnless { it.name.isNotEmpty() }?.also { println("姓名为空") }?: println(user.name)
repeat(5){
print(it)
println(user.name)
}
with(user){
this.name = "with"
}
println(user.name)
}
三、常用操作符
1,元素操作类
元素操作类 | 含义 |
---|
contains | 判断是否有指定元素 |
elementAt | 返回对应的元素,越界会抛 IndexOutOfBoundsException |
firstOrNull | 返回符合条件的第一个元素,没有则返回 null |
lastOrNull | 返回符合条件的最后一个元素,没有则返回 null |
indexOf | 返回指定元素的下标,没有则返回 -1 |
singleOrNull | 返回符合条件的单个元素,如果没有或超过一个,则返回 null |
package zyf.kotlin
fun main(args: Array<String>) {
val names = arrayOf("孙悟空","猪八戒","唐僧","沙和尚","白龙马","玉帝","王母娘娘","太白金星","太上老君","二郎神杨戬")
val contains = names.contains("孙悟空")
println("是否含有:$contains")
val elementAt = names.elementAt(2)
println("下标为2的元素是:$elementAt")
val firstOrNull = names.firstOrNull {
it.length == 2
}
println("符合长度是2的第一个元素是:$firstOrNull")
val lastOrNull = names.lastOrNull {
it.startsWith("太")
}
println("最后一个以'太'结尾的元素是:$lastOrNull")
val indexOf = names.indexOf("二郎神杨戬")
println("二郎神杨戬的下标为:$indexOf")
val singleOrNull = names.singleOrNull {
it.length == 5
}
println("长度为5的元素是:$singleOrNull")
val singleOrNull1 = names.singleOrNull {
it.length >= 2
}
println("长度大于等于2的元素是:$singleOrNull1")
}
2,判断类
判断类 | 含义 |
---|
any | 判断集合中是否有满足条件的元素 |
all | 判断集合中的元素,是否都满足条件 |
none | 判断集合中是否都不满足条件,是则返回true |
count | 查询集合中,满足条件的元素个数 |
reduce | 从第一项到最后一项进行累计 |
package zyf.kotlin
fun main(args: Array<String>) {
//判断类
val users = listOf(User("伏天氏"),User("飞剑问道"),User("大道朝天"))
val any = users.any {
it.name.length == 5
}
//any 只要有一个就能满足,一个没有就返回null
println("用户名字长度等于5的是:$any")
val all = users.all {
it.javaClass == User::class.java
}
println("元素类型是否都为User::class.java:$all")
val none = users.none {
it.name.length >= 3
}
println("集合中的元素的name长度是否都不大于等于3:$none")
val count = users.count {
it.name.length >= 3
}
println("集合中的元素的name长度大于等于3的数量为$count")
val demo = mutableListOf("张","李","周","郑")
val reduce = demo.reduce { acc, s ->
acc + s
}
println("从第一项累加到最后一项的结果为:$reduce")
}
3,过滤类
过滤类 | 含义 |
---|
filter | 过滤掉所有满足条件的元素 |
filterNot | 过滤掉所有不满足条件的元素 |
filterNotNull | 过滤NULL |
take | 返回前n个元素 |
package zyf.kotlin
fun main(args: Array<String>) {
val age = mutableListOf(1,2,3,4,5,6,7)
age.filter {
it>3
}.also {
println("过滤掉大于3的值后:$it")
}
age.filterNot {
it>3
}.apply {
println("过滤掉所有不满足大于3的值后(剩下的应该都是小于等于3的):$this")
}
val genders = listOf("男",null,"女")
val let = genders.filterNotNull().let { it[1] }
println("过滤掉NULL元素后,下标为1的元素是:$let")
val take = age.take(3)
println("前三个元素是:$take")
}
4,转换类
转换类 | 含义 |
---|
map | 转换成另一个集合(与前面的 convert 方法作用一样 |
mapIndexed | 除了转换成另一个集合,还可以拿到 Index |
mapNotNull | 执行转换后,过滤掉为 NULL 的元素 |
flatMap | 自定义逻辑合并两个集合 |
groupBy | 按照某个条件分组,返回 Map |
package zyf.kotlin
fun main(args: Array<String>) {
val loc = listOf("北京", "上海", "广州", "深圳", "杭州")
loc.map {
"$it 你好"
}.also {
println(it)
}
loc.mapIndexed { index, s ->
"这是第$index 个元素:$s"
}.also {
println(it)
}
val loc2 = listOf(null, "北京", "上海", "广州", "深圳", "杭州")
/**
* 经测试,并不是在转换前判断null
* 而是判断转换后的结果,结果为null,则被移除
*/
val mapNotNull = loc2.mapNotNull {
it
}
println("转换后的结果里有null,那么这个null就被移除了:$mapNotNull")
/**
* 所以下面的代码,依然会看到null
*/
val mapNotNull1 = loc2.mapNotNull {
it + 1
}
println("转换后的结果中没有null,只有[null1],并不会被移除:$mapNotNull1")
/**
* 在源码中,先创建一个空集合
* 然后遍历调用者(loc)
* 每次遍历,会将loc中的元素传入到闭包中(就是it)
* 然后将闭包的返回结果( listOf(it, it + 1)
* 添加到前面建立的新集合中
* 最后的结果就是:
*
* [listOf(it, it + 1),listOf(it, it + 1),listOf(it, it + 1),listOf(it, it + 1)...]
* it是loc遍历的元素,是从loc的第0位,一直遍历到底 loc.length-1 位的
*/
val flatMap = loc.flatMap {
listOf(it, it + 1)
}
println("转换后的结果:$flatMap")
/**
* 根据条件对集合中的元素进行分组,返回map
* 因为返回的是一个map,自然就需要指定key
* 下面语句1,就是在指定key
* 语句2,未指定key,则默认是true或false为key
*
*/
val groupBy = loc2.groupBy {
}
println(groupBy)
}
关于 flatMap
操作符的源码分析


5,排序类
排序类 | 含义 |
---|
reversed | 倒序 |
sorted | 升序 |
sortedBy | 自定义升序 |
sortedDescending | 降序 |
sortedByDescending | 自定义降序 |
package zyf.kotlin
fun main(args: Array<String>) {
val projects = listOf("语文","数学","外语","物理","化学","生物","政","历","地")
val reversed = projects.reversed()
println("倒序:$reversed")
val sorted = projects.sorted()
println("升序:$sorted")
val sortedBy = projects.sortedBy {
it.length
}
println("自定义排升序:$sortedBy")
val sortedDescending = projects.sortedDescending()
println("降序:$sortedDescending")
val sortedByDescending = projects.sortedByDescending {
it.length
}
println("自定义降序:$sortedByDescending")
}