class Student(val id: Int, val name: String)
fun main() {
val list = arrayListOf<Student>(Student(200, "Lim"), Student(100, "Kim"), Student(300, "Park"))
println(list.map { Student::name })
println(list.map { student -> student.name })
}
结果:
[val Student.name: kotlin.String, val Student.name: kotlin.String, val Student.name: kotlin.String]
[Lim, Kim, Park]
我不明白为什么会这样。
让我们来看看String::name
到底是什么。这是一个KProperty1<Student, String>
.此接口也实现了(Student) -> String
。因此,我们实际上是在处理一个 lambda,它将Student
作为参数并返回一个String
。
现在,map
函数需要什么?map
函数采用一个将某种类型映射到另一种类型的lambda((T) -> R
(,这意味着我们可以Student::name
传递给它。像任何函数一样,您将参数放在括号内。
list.map(Student::name) // variant 1
如果你想定义自己的lambda,你可以这样做:
val lambda: (Student) -> String = { it.name }
list.map(lambda) // variant 2
请注意 lambda 是如何作为参数在括号内传递的。如果您内联 lambda,则可以省略这些括号(并且 lambda 是该函数的最后一个参数(:
list.map { it.name } // variant 3
让我们看看你发生了什么。您在 lambda 中传递了引用:
list.map { Student::name }
这意味着您将列表中的任何元素转换为 Name 属性的引用。因此,您想要的是变体 1、2 或 3。
如注释中所述,您的第一个map
操作将引用映射到class Student
中name
字段的引用,然后打印该字段。
第二个映射每个Student
实例的该字段的值。
您可以使用字段引用来映射值,但必须为其使用略有不同的语法:map(...)
而不是map{ ... }
,请参阅以下示例:
fun main(args: Array<String>) {
val list = arrayListOf<Student>(Student(200, "Lim"), Student(100, "Kim"), Student(300, "Park"))
// map and print field reference of the class
println(list.map { Student::name })
// map and print field reference for each instance by lambda expression
println(list.map { student -> student::name })
// map and print values by field reference for each instance
println(list.map(Student::name))
// map and print values by transformation for each instance by lambda expression
println(list.map { student -> student.name })
}
因此,输出为
[val de.os.kotlin.Student.name: kotlin.String, val de.os.kotlin.Student.name: kotlin.String, val de.os.kotlin.Student.name: kotlin.String]
[val de.os.kotlin.Student.name: kotlin.String, val de.os.kotlin.Student.name: kotlin.String, val de.os.kotlin.Student.name: kotlin.String]
[Lim, Kim, Park]
[Lim, Kim, Park]