Java 8 Stream 等價物
關於懶惰
如果你想延遲處理一個鏈,你可以在鏈之前使用 asSequence()
轉換為 Sequence
。在功能鏈的末尾,你通常也會得到一個 Sequence
。然後你可以使用 toList()
,toSet()
,toMap()
或其他一些功能在最後實現 Sequence
。
// switch to and from lazy
val someList = items.asSequence().filter { ... }.take(10).map { ... }.toList()
// switch to lazy, but sorted() brings us out again at the end
val someList = items.asSequence().filter { ... }.take(10).map { ... }.sorted()
為什麼沒有型別?!?
你會注意到 Kotlin 示例未指定型別。這是因為 Kotlin 具有完整的型別推斷並且在編譯時完全是型別安全的。比 Java 更多,因為它也有可空型別,可以幫助防止可怕的 NPE。所以這在 Kotlin:
val someList = people.filter { it.age <= 30 }.map { it.name }
是相同的:
val someList: List<String> = people.filter { it.age <= 30 }.map { it.name }
因為 Kotlin 知道 people
是什麼,並且 people.age
是 Int
因此過濾器表示式只允許與 Int
進行比較,並且 people.name
是 String
因此 map
步驟產生 List<String>
(讀取 List
of String
)。
現在,如果 people
可能是 null
,那麼在一個 List<People>?
然後:
val someList = people?.filter { it.age <= 30 }?.map { it.name }
返回需要進行空檢查的 List<String>?
( 或使用其他 Kotlin 運算子之一獲取可空值,請參閱此 Kotlin 慣用方法來處理可空值以及處理可空或空列表的 慣用方法 )
重用流
在 Kotlin 中,它取決於收集的型別是否可以不止一次消費。Sequence
每次都會生成一個新的迭代器,除非它斷言只使用一次,否則它每次執行時都會重置為開始。因此,雖然以下在 Java 8 流中失敗,但在 Kotlin 中工作:
// Java:
Stream<String> stream =
Stream.of("d2", "a2", "b1", "b3", "c").filter(s -> s.startsWith("b"));
stream.anyMatch(s -> true); // ok
stream.noneMatch(s -> true); // exception
// Kotlin:
val stream = listOf("d2", "a2", "b1", "b3", "c").asSequence().filter { it.startsWith('b' ) }
stream.forEach(::println) // b1, b2
println("Any B ${stream.any { it.startsWith('b') }}") // Any B true
println("Any C ${stream.any { it.startsWith('c') }}") // Any C false
stream.forEach(::println) // b1, b2
並在 Java 中獲得相同的行為:
// Java:
Supplier<Stream<String>> streamSupplier =
() -> Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> s.startsWith("a"));
streamSupplier.get().anyMatch(s -> true); // ok
streamSupplier.get().noneMatch(s -> true); // ok
因此,在 Kotlin 中,資料提供者決定它是否可以重置並提供新的迭代器。但是如果你想故意將 Sequence
約束到一次迭代,你可以使用 constrainOnce()
函式為 Sequence
,如下所示:
val stream = listOf("d2", "a2", "b1", "b3", "c").asSequence().filter { it.startsWith('b' ) }
.constrainOnce()
stream.forEach(::println) // b1, b2
stream.forEach(::println) // Error:java.lang.IllegalStateException: This sequence can be consumed only once.
也可以看看:
- Iterable 擴充套件函式的 API 參考
- Array 的擴充套件函式的 API 參考
- List 的擴充套件函式的 API 參考
- 擴充套件函式到 Map 的 API 參考