为什么sumBy(selector)不返回Long类型?

28

决定是选择“最小惊讶”,这总是整数。 - voddan
4个回答

37
这是Kotlin团队做出的决定。由于Java中不可能有返回类型重载, 因此sumBy*必须根据返回类型具有不同的名称。
不过,自己添加sumByLong很容易:
inline fun <T> Iterable<T>.sumByLong(selector: (T) -> Long): Long {
    var sum = 0L
    for (element in this) {
        sum += selector(element)
    }
    return sum
}

25
我认为它应该在标准库中。 - voddan
var sum: Long = 0.0无法编译,我已将其更改为0L - Kirill Rakhman
1
谢谢。我还在学习Kotlin,所以我不得不去了解扩展函数。这些应该放在项目的哪个位置有惯例吗? - Jon Peterson
1
我通常将它们放在以接收类命名的文件中,例如 Iterable_.kt,但我也见过 Iterables.kt - miensol

15
你也可以使用 sum() 扩展函数,它还有一个 Long 变体,与 map() 结合使用。
val totalLength = files.map { it.length() }.sum()

或者您可以将此包装成扩展函数,尽管我没有看到与内联版本相比的太多好处:

inline fun <T> Iterable<T>.sumByLong(selector: (T) -> Long): Long {
    return map { selector(it) }.sum()
}

它比miensol的解决方案略微昂贵。 - kassim

7

你可以选择使用fold函数。

val totalLength = files.fold(0L) { acc, it -> acc + it.length() }

这段代码与 sumBy 代码相比并不长。


这应该是最好的答案。 - loalexzzzz

1
截至 Kotlin 1.4,你可以使用 sumOf,它根据函数参数的返回类型解析类型:
// prints 2^31 - 1 = 2147483647
println((0..30).sumOf{ 1 shl it })    

// prints -1 due to 32-bit overflow
println((0..31).sumOf{ 1 shl it })

// prints 2^32 - 1 = 4294967295 because it works with 64-bit longs
println((0..31).sumOf{ 1L shl it })

在 Kotlin Playground 中尝试一下:{{link1}}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接