2016-08-22 61 views
2

爲什麼這段Java代碼不能在Kotlin中編譯,而在Collectors.toList<String>()中沒有顯式類型參數?有沒有更習慣的方式來做到這一點?Java lambda類型推斷在Kotlin中沒有像預期的那樣工作

// works 
List<String> folders = Files.walk(Paths.get(args[0])) 
             .filter(it -> it.toFile().isDirectory()) 
           .map(it -> it.toAbsolutePath().toString()) 
           .collect(Collectors.toList()); 

// does not compile - resulting type is `MutableList<in String!>..List<Any?>?` which is not compatible to `List<String>` 
val folders: List<String> = Files.walk(Paths.get(args[0])) 
           .filter { it.toFile().isDirectory } 
           .map { it.toAbsolutePath().toString() } 
           .collect(Collectors.toList()) 

// compiles 
val folders: List<String> = Files.walk(Paths.get(args[0])) 
           .filter { it.toFile().isDirectory } 
           .map { it.toAbsolutePath().toString() } 
           .collect(Collectors.toList<String>()) 
+2

只是一個旁註,Kotlin有它自己的'File.walk'擴展方法。 –

+1

你已經偶然發現了類型推斷中的一個錯誤https://youtrack.jetbrains.com/issue/KT-11259 – Ilya

+0

@Ilya感謝您的鏈接 - 偉大的是已經有一張票。 – atamanroman

回答

0

我發現了兩種方法使它在兩個地方都沒有明確指定泛型的情況下工作。

要麼你可以指定全類型的變量與generic covariance

val folders: MutableList<in String> = Files.walk(Paths.get(args[0])) 
     .filter { it.toFile().isDirectory } 
     .map { it.toAbsolutePath().toString() } 
     .collect(Collectors.toList()) 

,或者你可以簡單地讓科特林做它的類型推斷變量(方法的不通用參數)

val folders2 = Files.walk(Paths.get(args[0])) 
     .filter { it.toFile().isDirectory } 
     .map { it.toAbsolutePath().toString() } 
     .collect(Collectors.toList<String>()) 
+0

'MutableList '很少會出現'collect'的結果。第二個解決方法是好的。 – Ilya

3

爲什麼這段Java代碼在Kotlin中沒有在Collectors.toList<String>()中顯式類型參數沒有編譯?

這看起來像是一個編譯器bug。我建議在Kotlin (KT) | YouTrack中創建一個問題。

有沒有更習慣的方法來做到這一點?

是的。如Kirill Rakhmancomments,「Kotlin有自己的File.walk擴展方法。」例如:

val folders: List<String> = File(args[0]).walk() 
     .filter(File::isDirectory) 
     .map(File::getAbsolutePath) 
     .toList() 

如果您更喜歡使用Java 8流,然後結賬Kotlin/kotlinx.support: Extension and top-level functions to use JDK7/JDK8 features in Kotlin 1.0。它定義了一個Stream<T>.toList()函數:

val folders: List<String> = Files.walk(Paths.get(args[0])) 
     .filter { it.toFile().isDirectory } 
     .map { it.toAbsolutePath().toString() } 
     .toList() 
+1

我想補充一點,'Stream .toList()'已經在Kotlin 1.1的標準庫中了https://github.com/JetBrains/kotlin/blob/1.1-M1/libraries/stdlib/jre8/ src/kotlin/streams/Streams.kt#L35 – Ilya

+0

嗨,當我使用File(path).walk()方法時,列表只包含來自路徑的目錄的名稱,但不包含此目錄內的文件。任何想法 ? – SWAppDev

相關問題