一、解构
Kotlin
中使用operator
关键字修饰函数,这样可以将一个函数标记为重载一个操作符或者实现一个约定。使用operator
关键字修饰函数并且函数名只能为component1
、component2
、component3
…时就是实现一个约定。
通过将该类实例赋值给一组变量,Kotlin
可以直接将对应函数的值按照component1
、component2
、component3
…的顺序赋值给该组变量,这个过程就叫"解构"。
class User(var age: Int, var name: String){
operator fun component1() = age
operator fun component2() = name
}
fun main(args: Array<String>) {
val user = User(11, "Irving")
//将该类实例赋值给一组变量
val (age, name) = user
println(age)
println(name)
}
解构更常用的是在遍历一个map
的时候,通过将map
中的每一对键值对赋值给一组变量(key, value)
,从而可以同时遍历key
和value
。
fun main(args: Array<String>) {
val map = mapOf("key1" to "value1", "key2" to "value2")
for((key, value) in map){
println("$key --> $value")
}
}
二、循环
Kotlin
中的循环有以下几种形式
-
使用
in
关键字,in
关键字后面为一个闭区间,表示从小到大遍历。for (i in 1..10){ print("$i ") }
结果:
-
使用
in
和until
关键字,in
关键字后面为一个左闭右开的区间。for (i in 1 until 10){ print("$i ") }
结果:
-
使用
in
和downTo
关键字,in
关键字后面为一个闭区间,表示从大到小遍历(Kotlin
中不允许直接使用10..1
这种方式从大到小遍历)。for (i in 10 downTo 1){ print("$i ") }
结果:
-
使用
setp
关键字配合其他关键字使用,表示步长
,默认setp
为1。for (i in 1..10 step 2){ print("$i ") }
结果:
-
使用
repeat
高阶函数,传入一个Lambda
表达式。repeat(10){ print("$it ") }
结果:
查看repeat
函数代码,本质上还是通过in
和until
关键字实现的。@kotlin.internal.InlineOnly public inline fun repeat(times: Int, action: (Int) -> Unit){ contract { callsInPlace(action) } for (index in 0 until times) { action(index) } }
三、集合操作符
Kotlin
中可以通过集合操作符直接对集合进行操作,从而得到想要的结果。
map:
对集合中的数据做改变,可以改变数据的类型。filter:
得到所有符合Lambda
闭包中操作的数据。find:
得到符合Lambda
闭包中操作的第一个数据。findLast:
得到符合Lambda
闭包中操作的最后一个数据。reduce:
含有两个参数(集合中相邻的两个参数,用于遍历整个集合),对这两个参数进行操作,返回一个新参数,要求类型与集合中的参数类型相同。......
fun main(args: Array<String>) {
val list = arrayListOf('a','b','c','d')
val a = list.map {
//将集合中的Char类型转换为Int类型
it - 'a'
}.filter {
//得到所有大于0 数
it > 0
}.findLast {
//得到最后一个大于1的数
it > 1
}
println(a)
}
自己定义集合操作符
Kotlin中
可以通过给Iterable
接口添加扩展函数来定义集合操作符,所有集合都可以直接调用自定义的集合操作符。
//定义一个集合操作符convert,作用类似于map
inline fun <T, E> Iterable<T>.convert(block: (T) -> E): MutableList<E>{
val list = mutableListOf<E>()
for (item: T in this) {
list.add(block(item))
}
return list
}
fun main(args: Array<String>) {
val list = arrayListOf('a', 'b', 'c', 'd')
list.convert {
it - 'a'
}.forEach {
print("$it ")
}
}
四、作用域函数
Kotlin
中的作用域函数和上面的集合操作符很类似,区别是Kotlin
中所有的对象都可以调用作用域函数。
创建一个User
对象:
data class User(var name: String)
fun main(args: Array<String>) {
val user = User("Irving")
}
-
let、run
:let
与run
都会返回闭包的执行结果,区别是let
有闭包参数,参数为执行闭包的这个对象,一般可以省略不写,用it
代替。user.let { println(it.name) //最后一行返回闭包的执行结果 "Hello World" } user.run { println(name) //最后一行返回闭包的执行结果 "Hello World" }
-
apply、also
:apply
和also
都会返回执行该闭包的对象,区别是also
有闭包参数,参数为执行闭包的这个对象,一般可以省略不写,用it
代替。user.apply { println(name) }.name//函数调用完返回执行该闭包的对象,所以可以继续调用该对象的属性 user.also { println(it.name) }
-
takeIf、takeUnless
:takeIf
的闭包返回一个判断结果,如果为false
时takeIf
函数返回null
;takeUnless
与takeIf
相反,为true
时takeUnless
函数返回null
。user.takeIf { it.name.isNotEmpty() }?.also { println(it.name) } ?: println("姓名为空") user.takeUnless { it.name.isEmpty() }?.also { println(it.name) } ?: println("姓名为空")
-
with:
with
函数不是以扩展函数存在的,而是一个顶级函数。with(user){ println(name) "test" }
通过查看
with
函数的源代码,可以知道with
函数相当于对接收到的对象进行传入的闭包操作。相当于在内部调用一次user.apply{}
,同时最后还能返回执行结果。public inline fun <T, R> with(receiver: T, block: T.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return receiver.block() }