聚合(Aggregate)操作
Kotlin 的集合包含一些函数, 用于实现常见的 聚合(Aggregate)操作 – 也就是根据集合内容返回单个结果的操作. 大多数聚合操作都是大家已经熟悉的, 并与其他语言中的类似操作的工作方式相同:
minOrNull()
和maxOrNull()
函数, 分别返回最小和最大的元素. 对空集合, 这些函数返回null
.average()
函数, 返回数值集合中元素的平均值.sum()
函数, 返回数值集合中元素的合计值.count()
函数, 返回集合的元素个数.
还有其他函数, 可以取得最小和最大元素, 但使用指定的选择器(selector)函数, 或自定义的 Comparator
:
maxByOrNull()
和minByOrNull()
函数, 参数是一个选择器(selector)函数, 返回的结果是, 经过选择器(selector)函数计算后的结果值最大或最小的那个元素.maxWithOrNull()
和minWithOrNull()
函数, 参数是一个Comparator
对象, 返回的结果是, 根据Comparator
的比较结果判定为最大或最小的那个元素.maxOfOrNull()
和minOfOrNull()
函数, 参数是一个选择器(selector)函数, 返回结果是, 选择器函数的结果值中的最大或最小值.maxOfWithOrNull()
和minOfWithOrNull()
函数, 参数是一个Comparator
对象, 返回的结果是, 选择器函数的结果值中, 根据Comparator
判定的最大或最小值.
这些函数都对空集合返回 return null
. 还有其他替代函数 – maxOf
, minOf
, maxOfWith
, 以及 minOfWith
– 这些函数与上面的各个函数功能相同, 但对空集合会抛出 NoSuchElementException
异常.
除通常的 sum()
函数外, 还有更高级的求和函数 sumOf()
, 它接受一个选择器函数作为参数, 返回结果是对集合所有元素执行这个选择器函数之后的合计结果. 选择器函数可以返回不同的数值类型: Int
, Long
, Double
, UInt
, 以及 ULong
(对 JVM 平台还支持 BigInteger
和 BigDecimal
).
折叠(fold) 与 简化(reduce)
对于更加专门的情况, 可以使用 reduce()
和 fold()
函数, 它们可以对集合中的元素顺序地执行指定的操作, 然后返回累计结果. 这些操作需要两个参数: 前一次计算的累计值, 以及当前处理中的集合元素.
这两个函数的区别是, fold()
通过参数指定初始值, 并把它用作第一步处理时的累计值, 而 reduce()
的第一步处理, 使用第一个和第二个元素作为操作参数.
上面的示例演示了它们的区别: 计算元素值加倍之后的合计值时, 我们使用了 fold()
函数. 如果将同样的计算函数传递给 reduce()
, 会得到不同的结果, 因为它在第一步计算时会使用 list 的第一个和第二个元素, 因此第一个元素不会被加倍.
如果要对集合元素以相反的顺序调用处理函数, 可以使用 reduceRight()
和 foldRight()
函数. 它们的工作方式与 fold()
和 reduce()
函数类似, 但从最末尾的元素开始, 然后继续处理前面的元素. 注意, 如果从右端开始进行折叠或简化操作, 那么计算函数得到的操作参数顺序也会改变: 第一个参数是元素值, 第二个参数是累计值.
执行操作时还可以使用元素下标作为参数. 这时请使用 reduceIndexed()
和 foldIndexed()
函数, 操作的第一个参数会是元素下标.
最后, 还有对应的函数, 可以对集合元素从右向左执行这样的操作 - reduceRightIndexed()
和 foldRightIndexed()
.
对于空的集合, 所有的简化(reduce) 操作都会抛出异常. 如果要得到 null
值, 请使用对应的 *OrNull()
函数:
如果你需要保存累加计算的中间结果值, 可以使用 runningFold()
(或者它的别名函数 scan()
) 和 runningReduce()
函数.
如果执行操作时需要使用元素下标作为参数, 请使用 runningFoldIndexed()
或 runningReduceIndexed()
函数.