Kotlin:列表中BigDecimal的总和

klc*_*klc 11 kotlin

我有一个我想要过滤的列表,然后返回一个带有金额总和的id地图:

val totalById = list
                    .filter { it.status == StatusEnum.Active }
                    .groupBy { it.item.id }
                    .mapValues { it.value.sumBy { it.amount } }
Run Code Online (Sandbox Code Playgroud)

"it.amount"是BigDecimal,但看起来sumBy只是Int.

对于Java 8,它将是:

Collectors.groupingBy(i-> i.getItem().getId(), Collectors.mapping(Item::getAmount, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))))

在Kotlin有办法吗?

Ily*_*lya 18

就像你Collectors.reducing在java中使用的一样,你可以在Kotlin中使用foldreduce扩展函数:

val bigDecimals: List<BigDecimal> = ...
val sum = bigDecimals.fold(BigDecimal.ZERO) { acc, e -> acc + e }
// or
val sum2 = bigDecimals.fold(BigDecimal.ZERO, BigDecimal::add)
Run Code Online (Sandbox Code Playgroud)

  • 我试过: .mapValues { it.value.map { it.amount}.fold(BigDecimal.ZERO, BigDecimal::add) 但编译器抱怨“::add”:以下任何函数都不能使用提供的参数调用: (2认同)

小智 9

在 Kotlin 1.4 中sumOf,他们介绍了它的用法:

val bigDecimals: List<BigDecimal> = ...
val sum = bigDecimals.sumOf { it }
Run Code Online (Sandbox Code Playgroud)

文档


mfu*_*n26 7

您可以创建类似于自己的sumByBigDecimal 扩展功能sumByDouble.例如:

/**
 * Returns the sum of all values produced by [selector] function applied to each element in
 * the collection.
 */
inline fun <T> Iterable<T>.sumByBigDecimal(selector: (T) -> BigDecimal): BigDecimal {
    var sum: BigDecimal = BigDecimal.ZERO
    for (element in this) {
        sum += selector(element)
    }
    return sum
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

val totalById = list
        .filter { it.status == StatusEnum.Active }
        .groupBy { it.item.id }
        .mapValues { it.value.sumByBigDecimal { it.amount } }
Run Code Online (Sandbox Code Playgroud)