<font face= 黑體>在 Kotlin 高階函數與內聯函數 中咱們已經將 Kotlin 的 高階函數 和 內聯函數 講完了,今天咱們來說 Kotlin 的 集合變換與聚合。java
<font face= 黑體>對於集合來講,最多見的使用方式就是對集合進行遍歷,咱們來看一下 Java 和 Kotlin 的遍歷集合代碼:
Java:git
// 普通的 for 循環遍歷 for(int i = 0; i <= 10; i++) { System.out.println(i); } // for each 遍歷 for(int e : list) { System.out.println(e); } // forEach 函數 list.forEach((e) - > { System.out.println(e); });
Kotlin:github
// 普通的 for 循環遍歷 for(i in 0 .. 10) { println(i) } // for each 遍歷 for(e in list) { println(e); } // forEach 函數 list.forEach { println(it); }
<font face= 黑體>在上面的 forEach 函數裏面不能 continue 或者 break,可是咱們有須要 break 和 continue 的需求要怎麼辦呢?其實咱們有專用的方法來解決這樣的需求,就是集合的 映射操做(Java 在 8 的時候也引入了這些操做,叫 流Stream),以下:segmentfault
函數名 | 說明 |
---|---|
filter | 保留知足條件的元素 |
map | 集合中的全部元素 —— 映射到其餘元素構成新集合 |
flatMap | 集合中的全部元素 —— 映射到新集合併合並這些集合獲得新集合 |
<font face= 黑體>好比咱們要從集合 [1, 2, 3, 4] 中將全部的偶數篩選出來,就能夠用 filter 操做來實現,以下:函數
Java:spa
list.stream() .filter(e -> e % 2 == 0);
Kotlin:code
list.filter { it % 2 == 0 }
<font face= 黑體>好比咱們要把集合 [1, 2, 3, 4] 中的全部元素乘以 2,變成一個新集合,就能夠用 map 操做來實現,以下:blog
Java:rem
list.stream() .map(e -> e * 2);
Kotlin:get
list.map { it * 2 }
<font face= 黑體>上面的 Kotlin 代碼還能夠寫成下面這樣:
list.asSequence().map { it * 2 }
<font face= 黑體>這兩種寫法區別主要是集合的操做是餓漢式的仍是懶漢式的,若是加上 asSequence 的話,集合的操做就變成了懶序列了。咱們經過下面的代碼來解釋這兩種方式:
Java:
List<Integer> list = new ArrayList<>(); list.addAll(Arrays.asList(1, 2, 3, 4)); list.stream() .filter(e -> { System.out.println("filter: " + e); return e % 2 == 0; }) .map(e -> { System.out.println("map: " + e); return e * 2 + 1; }) .forEach(e -> { System.out.println("forEach: " + e); });
Kotlin:
val list = listOf(1, 2, 3, 4) list.asSequence() .filter { println("filter: $it") it % 2 == 0 }.map { println("map: $it") it * 2 + 1 }.forEach { println("forEach: $it") }
<font face= 黑體>打印結果以下所示:
<font face= 黑體>從打印結果能夠看出,懶序列的執行方式是集合裏面的 1 走一遍完整的流程,走完以後 2 繼續走一遍完整的流程...,可是 1 呢在 filter 裏面判斷是否是偶數就不知足了,而後就是 2 走一遍完整流程,2 是知足 filter 的過濾的,因此 2 就到了 map 裏面映射成了 5,而後在 forEach 中輸出了,3 和 4 都是一樣的流程。
<font face= 黑體>若是咱們把 asSequence() 去掉,就變成了餓漢式,代碼以下:
val list = listOf(1, 2, 3, 4) list .filter { println("filter: $it") it % 2 == 0 }.map { println("map: $it") it * 2 + 1 }.forEach { println("forEach: $it") }
<font face= 黑體>從打印結果能夠看出,餓漢式在調用 filter 的時候立刻就會將集合所有過濾一遍,而後過濾以後的在去執行 map,等全部元素 map 操做都執行好以後,在執行 forEach。
<font face= 黑體>flatMap 操做能夠看下面的圖解:
<font face= 黑體>flatMap 的操做就是將一個元素映射成集合,而後再將這些集合合併起來。
<font face= 黑體>集合除了有上述的變換操做外,集合還有聚合操做,以下:
函數名 | 說明 |
---|---|
sum | 全部元素求和 |
reduce | 將元素依次按規則聚合,結果與元素類型一致 |
fold | 給定初始化值,將元素按規則聚合,結果與初始化值類型一致 |
<font face= 黑體>Kotlin 的集合的聚合操做相比來說沒有變換操做重要,這裏我就舉個 fold 函數的例子吧,以下:
// 計算過程爲 10 + 1 + 2 + 3,等於 16 val foldResult1 = arrayOf(1, 2, 3).fold(10, { a, b -> a + b }) println(foldResult1) //計算過程爲 10 * 1 * 2 * 3,等於60 val foldResult2 = arrayOf(1, 2, 3).fold(10, { a, b -> a * b }) println(foldResult2)
<font face= 黑體>fold 函數的操做以下:
<font face= 黑體>本篇博客主要講了 Kotlin 中的集合的變換與聚合,下一節咱們講 Kotin 的 SAM 轉換 和 經常使用高階函數。
源碼 已上傳至 github,有須要能夠直接下載。