Kotlin の fold()と reduce()の違い

David Mbochi Njonge 2023年1月30日
  1. Kotlin fold() メソッドの動作例
  2. Kotlin reduce() メソッドの実行例
  3. まとめ
Kotlin の fold()と reduce()の違い

fold() および reduce() メソッドは、Iterable インターフェースの拡張関数です。これらのメソッドは要素のリストを消費し、それらを単一の要素に変換します。

Collection インターフェースは Iterable インターフェースを実装しているため、Collection クラスのサブタイプである任意のクラスまたはインターフェースでメソッドを使用できます。

このチュートリアルでは、fold() メソッドと reduce() メソッドの違いを理解し、それぞれの場合の例を示します。

Kotlin fold() メソッドの動作例

IntelliJ にアクセスし、File > New > Project を選択して、新しいプロジェクトを作成します。プロジェクト名を kotlinFoldAndReduce または任意の名前で入力します。[言語]セクションで [Kotlin]を選択し、[ビルドシステム]セクションで [Intellij]を選択します。[作成]ボタンを押してプロジェクトを作成します。

プロジェクトが作成されたら、fold() メソッドの場合はフォルダー構造 com/fold を作成し、reduce() メソッドの場合は com/reduce を作成します。

fold フォルダの下に Main.kt という名前の新しいファイルを作成し、次のコードをコピーしてファイルに貼り付けます。

package com.fold

class Product(private val name: String,
               private val price: Int){

    fun getName(): String{
        return this.name;
    }

    fun getPrice(): Int{
        return this.price
    }
}

val  products: List<Product> = listOf(
    Product("Hp laptop",200),
    Product("Java book",320),
    Product("Iphone 13",150)
)

fun main() {
    println(products.fold(0) { total, employee ->
       total+employee.getPrice()
    });
}

このコードで作成した listOf() ヘルパーメソッドは、Product 要素のリストを返し、返されたリストから、fold() メソッドを呼び出すことができます。

fold() メソッドを呼び出すときは、計算のアキュムレータとして使用される初期値を指定する必要があります。返されたコレクションが空の場合、fold() メソッドは指定された初期値を返すことに注意してください。

以下に示すように、コードを実行して、リスト内のすべての製品要素の合計価格が出力されることを確認します。

出力:

670

fold() メソッドを使用して、少なくとも初期値よりも大きいか小さい値をチェックすることもできます。次の例では、リスト内のすべての product 要素をテストして、少なくとも 300 を超える product 価格を返すため、fold() 関数の初期値として 300 を設定します。

この例をコピーしてファイルに貼り付ける前に、main メソッドの前の例をコメントアウトしてください。

fun main() {
    println(products.fold(300) { expensiveProduct, product ->
        if (product.getPrice() > expensiveProduct)
            product.getPrice() else expensiveProduct
    });
}

コードを実行して、次の値が出力されることを確認します。リスト内のすべての product 要素の最大価格。

出力:

320

Kotlin reduce() メソッドの実行例

reduce フォルダーの下に Main.kt ファイルを作成し、次のコードをコピーしてファイルに貼り付けます。

package com.reduce

val list: List<Int> = listOf(20,40,60)

fun main() {
    println(list.reduce { sum, value ->
        sum + value
    });
}

reduce() メソッドには初期値がないため、リストの最初の要素を初期値として使用します。この例では、値 20 が最初のアキュムレータ値であり、40 を使用して計算すると次のアキュムレータ値が返されます。

コードを実行し、次の結果が出力されることを確認します。

出力:

120

前の例では、リストが空の場合に提供された初期値が返されることを学びました。リストが空の場合、reduce() メソッドは UnsupportedOperationExceptionRuntimeException をスローします。

reduce() メソッドが RuntimeException をスローしないようにするために、計算を行う前にリストが空かどうかを確認できます。次のコードは、int 型リストが空の場合に 0 の値を返します。

前の例にコメントし、この例をコピーしてコメントの後のファイルに貼り付けます。

package com.reduce

val list: List<Int> = listOf()

fun main() {
    val data = if (list.isEmpty()) 0
    else list.reduce { sum, value ->
        sum + value
    }
    println(data);
}

コードを実行し、作成したリストが空であるため、コンソールに記録される値が 0 であることに注意してください。

出力:

0

まとめ

このチュートリアルでは、fold()reduce() 拡張関数を区別する方法を学びました。また、スローされる可能性のある例外を回避するために、リストが空の場合に 2つのメソッドがどのように対処するかについても説明しました。

David Mbochi Njonge avatar David Mbochi Njonge avatar

David is a back end developer with a major in computer science. He loves to solve problems using technology, learning new things, and making new friends. David is currently a technical writer who enjoys making hard concepts easier for other developers to understand and his work has been published on multiple sites.

LinkedIn GitHub