kotlin学习 lambda编程
目录
- 集合
- list
- Map
- 集合的函数式api
- list.maxBy
- list.map()
- filter()
- any()
- all
- java函数式api
- 空指针检查
- 判空辅助工具
- ?:操作符
- !! 非空断言工具
- let函数
集合
list
listOf创建一个不可变的集合。无法对集合进行添加、修改或删除。
val list =listOf("张三","李四","王五")
mutableListOf创建一个可变的集合
val list2 =mutableListOf("张三","李四","王五")
set集合与上面类似。setof()和mutableSetOf()。
Map
val map = HashMap<String, Int>()map["张三"] = 1map["李四"] = 2map["王五"] = 3
从map中读取一条数据。
val number = map["张三"]
kotlin也提供了mapOf()和mutableMapOf()。
使用mapOf
val map2 = mapOf("张三" to 1 , "李四" to 2 ,"王五" to 3)
使用mutableMapOf
val map3 = mutableMapOf("张三" to 1 , "李四" to 2 ,"王五" to 3)
集合的函数式api
lambda语法结构:
{参数名1:参数类型,参数名2:参数类型 -> 函数体}
list.maxBy
找出最长的名字
val list = listOf("zhang san", "li si si", "gong sun wu ji")val maxName = list.maxBy { it.length }println(maxName)
gong sun wu jiProcess finished with exit code 0
maxBy接受lambda参数,上面不明显,下面的示例,就容易看出来了。
val list = listOf("zhang san", "li si si", "gong sun wu ji")val l = {name :String ->name.length}//lambdaval maxName = list.maxBy(l)println(maxName)
list.map()
map()将集合中的每个元素都映射成另外的值,生成一个新的集合。
转化成大写
val list = listOf("zhang san", "li si si", "gong sun wu ji")val newList = list.map { it.uppercase(Locale.ROOT) }println(newList)
结果
[ZHANG SAN, LI SI SI, GONG SUN WU JI]Process finished with exit code 0
filter()
用来过滤集合里的数据。
val list = listOf("zhang san", "li si si", "gong sun wu ji")val newList = list.filter { it.length <=10 }println(newList)
结果
[zhang san, li si si]Process finished with exit code 0
any()
用于判断集合中是否至少存在一个元素满足指定条件。
val list = listOf("zhang san", "li si si", "gong sun wu ji")val aList = list.any{it.length <=10}println(aList)
结果
true
all
用于判断集合中是否所有元素都满足指定条件。
val list = listOf("zhang san", "li si si", "gong sun wu ji")val allList = list.all { it.length <= 10 }println(allList)
false
java函数式api
在kotlin中调用java方法时可以使用函数式api,是有条件限制的,在kotlin代码中调用一个java方法,此方法有一个接口参数,且只有一个待实现方法,有多个待实现方法无法使用函数式api。
示例
Thread(object : Runnable{override fun run() {}}).start()
kotlin创建匿名类需要使用object :
简化后
Thread(Runnable{}).start()
如果一个java方法的参数列表中有且仅有一个java单抽象方法接口参数,可以将接口名省略。
Thread( {}).start()
当lambda表达式是方法的最后一个参数,可以将lambda表达式到方法括号的外面。如果lambda表达式还是方法的唯一一个参数。可以将方法的括号省略。如下:
Thread {}.start()
空指针检查
kotlin将空指针异常的检查提前到了编译时期。
可控类型系统,在类名的后面加上一个问号。
Int表示不为空的整形,Int?表示可为空的整形。String表示不可为空的字符串,String?表示可为空的字符串。
判空辅助工具
?. 当对象不为空时正常调用,当对象为空时,什么都不做。
示例
if(s!=null){s.test()}
使用?.后
s?.test()
?:操作符
左右两边都接受一个表达式,如果左边表达式的结果不为空就返回左边表达式的结果,否则就返回右边表达式的结果。
val a = if(b == 1){b
}else{c
}
使用?:
val a = b?:c
!! 非空断言工具
kotlin空指针检查机制并不是太智能,从逻辑上已经将空指针异常处理了,但是编译还是失败。
var content:String? = "test";fun main() {if(content !=null){printAdd()}
}fun printAdd(){val nc = content.toUpperCase()println(nc)
}
上面这段代码是不能运行的,这种情况就需要强行通过编译了,使用!!。
fun printAdd(){val nc = content!!.toUpperCase()println(nc)
}
let函数
将原始调用对象作为参数传递到lambda表达式中。
obj.let{obj2->}
下面举个代码的例子,便于理解let的优势。
interface Draw {fun paintTree()fun paintFish()
}fun paint(draw: Draw?) {draw?.paintFish()draw?.paintTree()
}
上面这个代码可以正常运行,转换成if判断
fun paint(draw: Draw?) {if(draw != null){draw.paintFish()}if(draw != null){draw.paintTree()}
}
可以看出每次使用draw对象时,都要进行一次if判断。这个时候就可以使用let函数和?.操作符来优化了。
draw?.let { dr->dr.paintTree()dr.paintFish()}
draw不为空时,就调用let函数,let函数会将draw对象传入到lambda中,dr对象肯定不为空。只有一个参数,省略声明参数名,使用it。
fun paint(draw: Draw?) {draw?.let {it.paintTree()it.paintFish()}
}
let函数可以处理全局变量的判空问题,if判断无法做到。
var draw: Draw? = nullfun paint() {if(draw !=null){draw.paintTree()draw.paintFish()}
}
这段代码会报错,是因为全局变量的值随时可能会被其他线程修改。即使做了判空处理,仍然无法保证if语句中的draw变量没有空指针风险。
