回答:
fold
は初期値を取り、それに渡すラムダの最初の呼び出しは、その初期値とコレクションの最初の要素をパラメーターとして受け取ります。
たとえば、整数のリストの合計を計算する次のコードを見てください。
listOf(1, 2, 3).fold(0) { sum, element -> sum + element }
ラムダの最初の呼び出しは、パラメーター0
とを使用します1
。
操作に何らかのデフォルト値またはパラメーターを提供する必要がある場合は、初期値を渡す機能があると便利です。たとえば、リスト内の最大値を探していたが、何らかの理由で少なくとも10を返したい場合は、次のようにします。
listOf(1, 6, 4).fold(10) { max, element ->
if (element > max) element else max
}
reduce
初期値を取りませんが、代わりにアキュムレータとしてのコレクションの最初の要素から開始しsum
ます(次の例で呼び出されます)。
たとえば、整数の合計をもう一度やってみましょう:
listOf(1, 2, 3).reduce { sum, element -> sum + element }
ここでのラムダの最初の呼び出しは、パラメータ1
とを使用します2
。
reduce
操作が、それを適用するコレクション内の値以外の値に依存しない場合に使用できます。
emptyList<Int>().reduce { acc, s -> acc + s }
は例外を生成しますが、問題ありませんemptyList<Int>().fold(0) { acc, s -> acc + s }
。
listOf<Int>(1, 2).reduce { acc: Number, i: Int -> acc.toLong() + i }
(リストタイプはIntで、アキュムレータタイプはNumberとして宣言され、実際にはLongです)
(他の回答のコメントに記載されていますが、理解するのは難しいかもしれません)空のコレクションに対して実行reduce
すると例外がスローされるという点で、私が呼び出す主な機能の違いです。
listOf<Int>().reduce { x, y -> x + y }
// java.lang.UnsupportedOperationException: Empty collection can't be reduced.
これは.reduce
、「データなし」のイベントで返す値がわからないためです。
これをと比較.fold
すると、「開始値」を提供する必要があります。これは、コレクションが空の場合のデフォルト値になります。
val result = listOf<Int>().fold(0) { x, y -> x + y }
assertEquals(0, result)
したがって、コレクションを別の(非関連)タイプの単一の要素に集約したくない場合でも(そうすること.fold
ができるだけです)、開始コレクションが空の場合は、コレクションを確認する必要がありますサイズを最初に、次に.reduce
、または単に使用.fold
val collection: List<Int> = // collection of unknown size
val result1 = if (collection.isEmpty()) 0
else collection.reduce { x, y -> x + y }
val result2 = collection.fold(0) { x, y -> x + y }
assertEquals(result1, result2)