2016-09-30 21 views
5

我有,我想过滤列表,然后返回地图ID与量的总和:科特林:在列表中BigDecimal的总和

val totalById = list 
        .filter { it.status == StatusEnum.Active } 
        .groupBy { it.item.id } 
        .mapValues { it.value.sumBy { it.amount } } 

“it.amount”是BigDecimal的,但看起来像sumBy仅限于Int。

对于Java 8这将会是:

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

有没有办法做到在科特林?

回答

7

就像你已经使用在Java Collectors.reducing,您可以在科特林使用foldreduce扩展功能:

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

我尝试: .mapValues {it.value.map {it.amount} .fold(BigDecimal.ZERO,BigDecimal的::添加) 但complierr抱怨 “::增加”: 无下列功能可以是使用提供的参数调用: – klc

+0

[错误]私人打开乐趣添加(p0:BigInteger!,p1:Int,p2:BigInteger!,p3:Int):BigDecimal!定义在java.math.BigDecimal中 [错误] private open fun add(p0:Long,p1:Int,p2:BigInteger!,p3:Int):BigDecimal!定义在java.math.BigDecimal中 [错误] private open fun add(p0:Long,p1:Int,p2:Long,p3:Int):BigDecimal!定义在java.math.BigDecimal中 [错误] private open fun add(p0:Long,p1:Long):在java.math.BigDecimal中定义的长定义 [ p2:Int):BigDecimal!在java.math.BigDecimal的 – klc

+0

@klc定义,我制作一个完整的例子,它的工作原理:http://try.kotlinlang.org/#/UserProjects/cpohvnjtfr0uvpvcjc3gt02b1t/n0j3v72oh55hdf141663os6eek,你可以自己有尝试。 – Ilya

3

您可以创建自己的sumByBigDecimalextension function类似于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 
} 

用法示例:

val totalById = list 
     .filter { it.status == StatusEnum.Active } 
     .groupBy { it.item.id } 
     .mapValues { it.value.sumByBigDecimal { it.amount } } 
+0

有什么办法使内联函数具有全局性?正如你所看到的,sumByBigDecimal被用于整个应用程序。 – klc

+1

该功能默认情况下为全局@klc。它可以在任何地方导入和使用。 –