Kotlin 集合的變換與聚合

1、前言

<font face= 黑體>在 Kotlin 高階函數與內聯函數 中咱們已經將 Kotlin 的 高階函數內聯函數 講完了,今天咱們來說 Kotlin 的 集合變換與聚合java

2、集合變換與聚合

2.一、集合的變換操做

<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 集合中的全部元素 —— 映射到新集合併合並這些集合獲得新集合

2.1.一、filter 操做

<font face= 黑體>好比咱們要從集合 [1, 2, 3, 4] 中將全部的偶數篩選出來,就能夠用 filter 操做來實現,以下:函數

Java:spa

list.stream()
     .filter(e -> e % 2 == 0);

Kotlin:code

list.filter { it % 2 == 0 }

2.1.二、map 操做

<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。

2.1.三、flatMap 操做

<font face= 黑體>flatMap 操做能夠看下面的圖解:
flatMap 操做

<font face= 黑體>flatMap 的操做就是將一個元素映射成集合,而後再將這些集合合併起來。

2.二、集合的聚合操做

<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 函數的操做以下:

  1. <font face= 黑體>第一次執行時,由初始值 10 做爲參數 a,由集合中第 0 個元素做爲參數 b;
  2. <font face= 黑體>第二次執行時,第一次執行的返回值做爲參數 a,由集合中第 1 個元素做爲參數 b;
  3. <font face= 黑體>依次類推...;
  4. <font face= 黑體>最終將結果返回。

三 、小結

<font face= 黑體>本篇博客主要講了 Kotlin 中的集合的變換與聚合,下一節咱們講 Kotin 的 SAM 轉換經常使用高階函數

4、源碼

源碼 已上傳至 github,有須要能夠直接下載。​

相關文章
相關標籤/搜索