[英]What is the difference between filter () and {} in Kotlin
我正在学习 Kotlin,并且在理解带括号和花括号的过滤器之间的区别时遇到了一些困难。 如果我检查过滤器实现,Intellij 会将我重定向到同一个源。
代码示例:
listOf("john", "dave").filter { name -> name.startsWith("j") }
// versus
// simple predicate function
fun getSimplePredicate(): (String) -> Boolean =
name: String -> name.firstName.startsWith(prefix)
// actual filter call
listOf("john", "dave).filter(getSimplePredicate())
如果我想以某种方式调用filter { getSimplePredicate() }
怎么办?
有办法吗? 有什么区别? 提前致谢
filter()
需要一个谓词函数作为参数,即一个接受字符串并返回布尔值的函数。
在 Kotlin 中,如果函数的最后一个参数(这里是过滤器)是一个函数(谓词),那么你可以传递一个 lambda,并且 lambda 可以在括号之外。 所以
.filter { ... }
是相同的
.filter({ ... })
因此,在您的代码中, { name -> name.startsWith("j") }
是一个 lambda,它是传递给filter()
的参数。
函数getSimplePredicate()
返回一个谓词函数。
所以.filter(getSimplePredicate())
相当于.filter({ name.firstName.startsWith(prefix) })
,相当于.filter { name.firstName.startsWith(prefix) }
。
如果{ getSimplePredicate() }
是一个返回布尔值的函数,即如果getSimplePredicate()
返回一个布尔值,则.filter { getSimplePredicate() }
将是有效的。 但它没有,所以它是无效的。
正如 JB Nizet 所提到的,这并非特定于过滤,而是标准的 Kotlin 语法。 如果您使用 lambda 作为最后一个参数调用函数,例如:
list.map({ size -> size * 2 })
然后你可以将 lambda 移到括号外:
list.map(){ size -> size * 2 }
(这主要是为了允许看起来像新语言语法的函数。但它通常很有用。)如果它们中没有任何东西,你可以完全省略括号:
list.map{ size -> size * 2 }
此外,如果 lambda 仅具有一个参数(并且编译器可以推断其类型),那么您可以将其称为it
而不是显式命名它:
list.map{ it * 2 }
所有四种形式的含义完全相同:它们使用 lambda 调用map()
函数。 (您会经常看到这类语法快捷方式;它们有助于使代码更易于阅读。)
好的,进入你的代码:
您的第一行有效,但您的谓词函数在编译之前需要进行一些调整。 签名很好,但如果没有大括号,定义将无法工作。 (在 Scala 和 Java 中,箭头是显着的部分;但我们刚刚看到了如何在 Kotlin 中省略它,因此每个 lambda 都必须有大括号。)
此外,您还没有定义firstName
或prefix
。 我将假设我们可以忽略前者,并将后者作为参数提供。 稍微简化一下,得出:
fun getSimplePredicate(prefix: String): (String) -> Boolean
= { it.startsWith(prefix) }
通过这些调整,您确实可以使用它来提供过滤谓词,例如:
listOf("john", "dave").filter(getSimplePredicate("j"))
(请注意,这一次没有大括号,因为我们没有在这一行中创建 lambda - 函数已经这样做了。)
当然,在这种情况下,根据您的第一个示例,直接提供 lambda 实际上更简单! 但这说明了原理。
还有另一个值得一提的选项,它是函数引用。 如果您已经有一个可以完成这项工作的函数,则无需将其放入 lambda 中,但可以使用::
符号直接引用它。 例如:
fun hasValidPrefix(s: String) = s.startsWith("j")
listOf("john", "dave").filter(::hasValidPrefix)
这仅在参数类型兼容时才有效,但它稍微简单一些(并且可以生成稍微更有效的字节码)。
所有这些都在 Kotlin 文档中进行了解释。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.