lambda表达式也称λ 表达式,本质上就是可以传递给其他函数的一小段代码。
class Button() {
fun setOnClickListener(onClickListener: (OnClickListener) -> Unit) {
}
}
val button = Button()
button.setOnClickListener {
.........事件触发回调
}
上述Button中setOnClickListener方法接收一个 (OnClickListener) -> Unit
lambda表达式,即:函数的参数是一个lambda表达式类型,这就是Kotlin,当然阔以使用匿名内部类:
view.onClickListener = object : OnClickListener {
override fun onClick(view: View) {
}
}
这不是本节的内容,开始放大招了:结合Lambda+集合,最常用就是使用Lambda操作集合:
//构造几个Person
data class Person(val name: String, val age: Int)
val persons: ArrayList<Person> = ArrayList()
for (count in 0..10) {
persons.add(Person("name$count", count + 2))
}
persons.filter { it -> it.age % 3 == 0 }.map(Persion::name).forEach(::println)
看看这段代码,filter:就是过滤不满足it.age % 3 == 0 条件的元素,返回List<Person>,map:变换,最后返回List<String>;
看一些filter方法的源码:
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
.....
}
看函数的参数:predicate: (T) -> Boolean,Lambda表达式,解析一下,T:泛型,从Iterable<T> ,在这个例子T就是就是Person ,返回值是Boolean,就是例子中的it.age % 3 == 0的结果,这些只是Lambda表达式的返回值,函数返回是一个列表List<T>,集合的变换中间会产生一个新的集合,在上几个操作集合常用的栗子?
//过滤
persons.filter { it -> it.age % 3 == 0 }.map(Persion::name).forEach(::println)
//List<Person> -> List<String> -> println
persons.map(Persion::name).forEach(::println)
//List<Person> -> maxPerson - println
persons.maxBy(Persion::age).run(::println)
//List<Person> -> sumAge -> println
persons.sumBy(Persion::age).let(::println)
println(persons.all { it.age > 10 })//匹配所有
println(persons.any { it.age > 12 })//至少匹配一个
println(persons.count { it.age > 12 })//满足该条件的元素个数
println(persons.firstOrNull { it.age > 10 }?.name)//返回第一个或者返回null
println(persons.groupBy { it.age })//按年龄分组 ,返回一个map:key = it.age,value=Person
val books = ArrayList<Book>()
for (index in 0..10) {
books.add(Book("book$index", listOf("author$index", "author2$index")))
}
books.flatMap { it.authors }.toList().forEach(::println)
val strings = listOf("abc", "def")
println(strings.flatMap { it.toList() })//
我刚刚在上面提了一下,这些操作中间会产生临时列表:
persons.filter { it -> it.age % 3 == 0 }.map(Persion::name)
filter和map都会返回一个列表,即:上面的链式调用会创建两个列表,数据少还好,要是百万级的,那就jj,怕不怕?反正我是怕了,有没有解决方案呢?答案是肯定滴,该序列上场了。
//序列
persons.asSequence().map(Persion::name).filter { it.startsWith("A") }.toList()
Sequence 好像是Kotlin中惰性集合的入口,序列不需要创建中间列表来保存中间产生的数据。
Sequence 是什么?
就是一个可以逐个列举元素的元素序列
执行序列操作:中间和末端操作
序列操作分为两类:中间和末端操作,一次中间操作返回的是另一个序列,一次末端操作返回的是一个结果:
persons.asSequence().map(Persion::name).filter { it.startsWith("A") }.toList()
map和filter是中间的操作,toList()为末端操作,中间操作始终都是惰性的
persons.asSequence().map(Persion::name).filter {
println(it)
it.startsWith("A")
}
println(it)始终不会被执行(末端操作没有被调用;
persons.asSequence().map(Persion::name).filter {
println(it)
it.startsWith("A")
}.toList()
Sequence 和 列表的区别:列表会先把原始的列表变换成另一个列表,然后在从新列表中find,而Sequence 所有的操作是按顺序应用在每一个元素张,处理完第一个元素(先map在find),然后完成接着第二个元素的处理,find方法是返回的是第一个匹配元素。
val listOf = listOf(1, 2, 3, 4)
val map = listOf.map {
println(it)
it + 5
}.find {
println(it)
it > 3
}
listOf.asSequence().map {
println(it)
it + 5
}.find {
println(it)
it > 3
}
第一段结果是:1 2 3 4 6
第二段结果:1 6
很明显Sequence find的次数少于列表,性能优于列表,记住了老铁。
如何创建Sequence?
前面的栗子都是使用同一个方法创建Sequence :在集合上调用asSequence(),现在来说一下generateSequence函数。
val takeWhile = generateSequence(0) {
println(it)
it + 1
}.takeWhile { it <= 100 }
println(takeWhile.sum())
File("hello.txt").isHideden().let(::println)
fun File.isHideden() = generateSequence(this) {
it.parentFile
}.any {
it.isFile
}
网友评论