Kotlin学习(4)Lambda
记住Lambda的本质,还是一个对象。和JS,Python等不同的是,Kotlin里的Lambda不是方法,而是一个简化了的对象。
此外,Kotlin里面的没有匿名函数这一说,函数也不是传统的对象。
看看Kotlin的Lambda
//Java
button.setOnClickListener(v -> {//...})
//Kotlin
button.setOnClickListen{//...}
一个Lambda函数
it是一个lamdba隐含对象,可能是Iterable的简写吧
data class Person(val name: String, val age: Int)
fun main(vararg args: String){
val people = listOf<Person>( Person("Alice",29), Person("Bob",31) ) //使用隐含对象 println(people.maxBy { it.age }) //使用成员对象引用 println(people.maxBy(Person::age)) //类Java println(people.maxBy{ p: Person -> p.age}) }
Lambda句法
//Java
static IntBinaryOperator add = (x, y) -> x + y;
public static void main(String...args){ add.applyAsInt(1,2) } //Kotlin val sum = { x: Int, y: Int -> x + y } fun main(vararg args: String){ sum(1,2) }
咋一看挺迷惑的,需要看看Java中的写法
因为上面说了Lambda是个对象,那么对象能像函数一样调用呐?
证实了我们的观点,确实是个对象,sum()应该是sum.invoke()的语法糖吧
直接调用Lambda
{ x: Int, y: Int -> x + y }(1,2)
//run适用于无参数的Lambda
run { print(24)}
看一个例子
transform申明要一个Lambda参数
public fun <T> Iterable<T>.joinToString(
separator: CharSequence = ", ",
prefix: CharSequence = "",
postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String { return ... }
在Lambda中使用可变变量
在Java中,Lambda中不能使用变量,如下
public static void main(String...args){
int i = 0; Runnable r = () -> { i++;//会报错 }; } //只能这么做 static class I{ public static int i = 0; } public static void main(String...args){ Runnable r = () -> { I.i++; }; }
但是在Kotlin中可以
var count = 0
val inc = { count++ }
- 1
- 2
成员引用
可以视为Java反射包中的Field和Method
data class Person(val name: String, val age: Int)
Person::age//property age
fun sulate() = println("aaa") val a = run(::salute)//function add //构造器引用 val createPerson = ::Person val p = createPerson("Alice", 29) val personAgeFunction = Person::age println(personAgeFunction(p)) //29 val thisPersonAgeFunction = p::age println(thisPersonAgeFunction()) //29
最后两个例子可能有些疑惑,但本质personAgeFunction还是一个对象,像函数一样调用还是一个语法糖(personAgeFunction.get())
函数式API
典型的声明式编程,和SQL语句有共同之处。语义很好理解,不解释了
- filter
- map: map是将集合中的每个元素变成另一种A->B
- filterKeys
- mapKeys
- filterValues
- mapValues
- all
- any
- count
- find
- groupBy
val people = listOf<Person>(
Person("a",19),
Person("b",28),
Person("c",19), Person("d",20) ) val result = people.groupBy { it.age } println(result) println(result.javaClass) /* {19=[Person(name=a, age=19), Person(name=c, age=19)], 28=[Person(name=b, age=28)], 20=[Person(name=d, age=20)]} class java.util.LinkedHashMap */
- flatMap: flatMap将每个元素变成一个集合再合并这些集合A->[1,2…]
- flatten
- toList()
- toSet()
- asSequence: 类似于Java8的stream()
//传统链式调用,会产生一个map的结果和一个filter的List结果
//当集合很大时,有很大的性能开销
val result = people.map { it.age }
.filter { it > 20 } //改为使用asSequence(),最后别忘了加上toList() val result = people.asSequence() .map { it.age } .filter { it > 20 } .toList()
创建Sequence
val number = generateSequence(0) { it + 1 }
val numbersTo100 = number.takeWhile { it <= 100 } println(numbersTo100.sum())
使用map函数对集合进行操作
fun main(args: Array<String>) {
val list:Array<Int> = arrayOf(1,2,3,4,5,6,7,8)
val newList = list.map {
it*5+10
}
val doubleList = list.map(Int::toDouble)
newList.forEach(::println)
doubleList.forEach(::println)
}
使用flatMap对集合数据进行合并成一个集合
fun main(args: Array<String>) {
val list = arrayOf(
1..10,
20..30,
50..100
)
val mergeList = list.flatMap {
it.map {
"No.$it"
}
}
mergeList.forEach(::println)
}
使用reduce对集合进行计算操作
fun main(args: Array<String>) {
val list = arrayOf(
1..10,
20..30,
50..100
)
val mergeList = list.flatMap { it }
mergeList.forEach(::println)
println("总和:${mergeList.reduce(Int::plus)}")
println("总和:${mergeList.reduce { acc, i -> acc + i }}")
/**
* 方式1
*/
(0..6).map {
factorial(it)
}.forEach(::println)
/**
* 方式2
*/
(0..6).map(::factorial).forEach(::println)
}
/**
* 求阶乘
*/
fun factorial(int: Int): Int {
if (int == 0) return 1
return (1..int).reduce { acc, i -> acc * i }
}
使用fold对集合进行自定义计算
fun main(args: Array<String>) {
/**
* 对集合进行转化和拼接
*/
val _str: String = (0..10).joinToString(",")
println(_str)
/**
* 添加一个初始值
* 打印结果=》9
*/
println((0..1).fold(8) { acc, i ->
acc + i
})
/**
* 添加一个StringBuilder的初始值与集合中的元素进行计算操作
*/
val _str1 = (0..5).fold(StringBuilder()) { acc, i ->
acc.append(i).append(",")
}
println(_str1)
}
---------------------