集約オペレーション(aggregate)
Kotlinのコレクションは良く使われる集約(aggregate)オペレーションの関数を含んでいる。 集約オペレーションとは、コレクションの中身を元に単一の値を返すオペレーションの事です。 多くのものは良く知られていて、他のプログラム言語のものと同様に振る舞います:
minOrNull()
とmaxOrNull()
は最小と最大の要素をそれぞれ返す。空のコレクションに対して行うとnull
を返す。average()
は数値のコレクションの平均値を返す。sum()
は数値のコレクションの合計を返す。count()
コレクションの要素数を返す。
最小と最大の要素を、何らかのセレクタ関数やカスタムなComparator
を元にして返す関数もある:
maxByOrNull()
とminByOrNull()
はセレクタ関数を引数にとり、そのセレクタが返した値が最大の要素と最小の要素をそれぞれ返す。maxWithOrNull()
とminWithOrNull()
はComparator
オブジェクトを引数に取り、そのComparator
による最大と最小の要素をそれぞれ返す。maxOfOrNull()
とminOfOrNull()
はセレクタ関数を引数に取り、セレクタが返した最大の値か最小の値をそれぞれ返す。maxOfWithOrNull()
とminOfWithOrNull()
はComparator
オブジェクトを引数に取り、セレクタの返した値をComparator
基準で最大の値か最小の値を返す。(訳注:Comparator
とセレクタの2つの関数を引数に取る)
これらの関数は、空のコレクションに対してはnull
を返す。
この挙動だけが違う代替バージョンもある。
maxOf
、 minOf
、 maxOfWith
、 minOfWith
などです。
これらの関数はそれぞれの対応するものと同じ挙動をするけれど、空のコレクションに対してはNoSuchElementException
を投げます。
普通のsum()
の他に、より高度なsum関数、sumOf()
関数もあります。
これはセレクタ関数を引数に取り、それを全要素に適応した結果の合計を返します。
セレクタは異なる数値型を返しても構いません:Int
, Long
, Double
, UInt
, ULong
など (JVMの場合は BigInteger
と BigDecimal
もOK)。
foldとreduce
より特殊なケースのためには、reduce()
と fold()
関数があります。これは渡されたオペレーションをコレクションの要素に順番に適用していって、累積した結果を返します。
オペレーションは引数2つを取ります:前回までに累積した値と、コレクションの要素です。
reduceとfoldの違いは、fold()
は初期値を引数に取り、それを最初のステップでの累積値として用いるのに対し、
reduce()
は最初のステップとしては1つ目と2つ目の要素を引数に実行する所が違いです。
上の例は両者の違いを示しています: fold()
を使って要素を二倍したものの合計を計算しています。
同じ関数をreduce()
に渡すと、異なった結果を返します。
なぜならリストの最初と二番目の要素を最初のステップの引数にしますが、
そのため最初の要素が2倍されない為です。
逆順に関数を適用していきたければ、
reduceRight()
とfoldRight()
関数を使いましょう。
これらの関数はfold()
と reduce()
と似たように振る舞いますが、
最後の要素から始まって一つ前、その一つ前、と続いていく所が違います。
reduceRightとfoldRightはオペレーションの引数の順番が変わる事に注意してください: 1つ目の引数が要素で二つ目の引数が累積値となります。
要素のインデックスも引数に取るオペレーションを適用する事も出来ます。
この場合はreduceIndexed()
とfoldIndexed()
関数を使います。
要素のインデックスはオペレーションには最初の引数として渡されます。
最後に、そのようなオペレーションを右から左に適用する関数もあります。reduceRightIndexed()
とfoldRightIndexed()
です。
すべてのreduce系の関数は空のコレクションには例外を投げます。代わりにnull
を受け取りたければ、それらの対応する*OrNull()
バージョンを使ってください:
途中の累積値を保存したい場合は、
runningFold()
(またはその省略名の scan()
)
とrunningReduce()
関数があります。
オペレーションにインデックスのパラメータが必要な場合は、runningFoldIndexed()
か
runningReduceIndexed()
を使ってください。