[英]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.