In this Kotlin tutorial, I will show you some examples that uses sum()
, sumBy()
, sumByDouble()
for List, Map. We’re gonna create sum()
& sumByBigDecimal()
which also work for List of BigDecimal
objects.
Related Posts:
– Kotlin List & Mutable List tutorial with examples
– How to work with Kotlin HashMap
– Kotlin Fold Example: fold(), foldRight(), foldIndexed(), foldRightIndexed()
– Kotlin groupBy(), groupingBy() example
Contents
Kotlin sum()
The examples show you how to use sum() function to:
- sum of all items in the normal List
- sum of specific field in List of Objects (in need of
map()
) - sum of specific field of all values in a Map (in need of
map()
)
Why we need map()
?
map()
will create a List of quantity first, then we invoke: List<quantity>.sum()
List
We’re gonna use sum()
on List<Int>
and List<Double>
for example.
val nums = listOf(10, 20, 30)
println(nums.sum())
// 60
val doubles = listOf(1.05, 2.05, 3.65)
println(doubles.sum())
// 6.75
sum()
function can also work with List of Byte
, Short
, Long
, Float
items.
List of Objects
Now we will calculate total quantity of all Product(name, quantity, price) objects in List using sum()
.
Now we create a simple data class Product
like this.
package com.bezkoder.kotlin.sum
data class Product(val name: String, val quantity: Int, val price: Double) {
}
Then we initialize List<Product>
and we need to use map()
to get the List of quantity objects before applying sum()
on the result.
package com.bezkoder.kotlin.sum
fun main(args: Array<String>) {
val products = listOf(
Product("A", 10, 6.90),
Product("B", 20, 3.45),
Product("C", 30, 1.05)
)
val totalQuantity: Int = products.map { it.quantity }.sum()
println(totalQuantity)
// 60
}
Map
For Map
, we also need to get the List of quantity objects before using sum()
. It can be done with map()
function.
val productsMap = mapOf(
"a" to Product("A", 10, 6.90),
"b" to Product("B", 20, 3.45),
"c" to Product("C", 30, 1.05)
)
val totalQuantity: Int = productsMap.map { it.value.quantity }.sum()
println(totalQuantity)
// 60
Kotlin sumBy()
The examples show you ways to use sumBy() function to:
- sum (and change value to
Int
) of all items in the normal List - sum of specific
Int
field in List of Objects (no needmap()
) - sum of specific
Int
field of all values in Map of Objects (no needmap()
)
Why we don’t need map()
?
Look at protoype of sumBy()
function:
inline fun sumBy(selector: (T) -> Int): Int
You can see that sumBy()
receives a selector
which indicates the field to be processed.
List
import kotlin.math.roundToInt
val nums = listOf(10, 20, 30)
println(nums.sumBy { it })
// 60
println(nums.sumBy { it * 2 })
// 120
val doubles = listOf(1.05, 2.05, 3.65)
println(doubles.sumBy { it.roundToInt() })
// 7
sumBy()
function can also work with List of Byte
, Short
, Long
, Float
items.
List of Objects
Our work is simple now, just use sumBy()
like this: sumBy { it.quantity }
.
val products = listOf(
Product("A", 10, 6.90),
Product("B", 20, 3.45),
Product("C", 30, 1.05)
)
val totalQuantity: Int = products.sumBy { it.quantity }
println(totalQuantity)
// 60
Map
For Map<String, Product>
, we use map()
to get the List of Product
objects before applying sumBy()
on the result.
val productsMap = mapOf(
"a" to Product("A", 10, 6.90),
"b" to Product("B", 20, 3.45),
"c" to Product("C", 30, 1.05)
)
val totalQuantity: Int = productsMap.map { it.value }.sumBy { it.quantity }
println(totalQuantity)
// 60
Kotlin sumByDouble()
sumBy()
always returns integer value. To work with Double
, Kotlin provides sumByDouble() that calculate sum of all values produced by selector
function applied to each item in the List.
inline fun sumByDouble(selector: (T) -> Double): Double
The examples show you ways to use sumByDouble()
function to:
- sum of all
Double
items in the normal List - sum of specific
Double
field in List of Objects (no needmap()
) - sum of specific
Double
field of all values in Map of Objects (no needmap()
)
List
val doubles = listOf(1.05, 2.05, 3.65)
println(doubles.sumByDouble { it })
// 6.75
println(doubles.sumByDouble { it * 2 })
// 13.5
List of Objects
We’re gonna use sumByDouble()
to get total price by calculating sum of (quantity * price) of each Product
type.
val products = listOf(
Product("A", 10, 6.90),
Product("B", 20, 3.45),
Product("C", 30, 1.05)
)
val totalPrice: Double = products.sumByDouble { it.quantity * it.price }
println(totalPrice)
// 169.5
Map
val productsMap = mapOf(
"a" to Product("A", 10, 6.90),
"b" to Product("B", 20, 3.45),
"c" to Product("C", 30, 1.05)
)
val totalPrice: Double = productsMap.map { it.value }.sumByDouble { it.price * it.quantity }
println(totalPrice)
Kotlin sum() & sumBy() for List of BigDecimal
Assume that we have a List of BigDecimal objects like this.
import java.math.BigDecimal
val bigDecimals = listOf(
BigDecimal(124567890.0987654321),
BigDecimal(987654321.123456789),
BigDecimal(1122334455.66778899)
)
If we use sum()
function on the List: bigDecimals.sum()
. What happens?
Compiler will show an error:
None of the following functions can be called with the arguments supplied
None of the following functions can be called with the arguments supplied:
@JvmName public fun Iterable<Byte>.sum(): Int defined in kotlin.collections
@JvmName public fun Iterable<Double>.sum(): Double defined in kotlin.collections
@JvmName public fun Iterable<Float>.sum(): Float defined in kotlin.collections
@JvmName public fun Iterable<Int>.sum(): Int defined in kotlin.collections
@JvmName public fun Iterable<Long>.sum(): Long defined in kotlin.collections
@JvmName public fun Iterable<Short>.sum(): Int defined in kotlin.collections
@JvmName @SinceKotlin @ExperimentalUnsignedTypes public fun Iterable.sum(): UInt defined in kotlin.collections
@JvmName @SinceKotlin @ExperimentalUnsignedTypes public fun Iterable.sum(): UInt defined in kotlin.collections
@JvmName @SinceKotlin @ExperimentalUnsignedTypes public fun Iterable.sum(): ULong defined in kotlin.collections
It’s because Kotlin doesn’t either provide sum()
or sumByBigDecimal()
for BigDecimal
type. So we need to create the extension functions.
sum() BigDecimal
Let’s make our sum()
extension function like the following code.
fun Iterable<BigDecimal>.sum(): BigDecimal {
var sum: BigDecimal = BigDecimal.ZERO
for (element in this) {
sum += element
}
return sum
}
Now you can use bigDecimals.sum()
freely.
val bigDecimals = listOf(
BigDecimal(124567890.0987654321),
BigDecimal(987654321.123456789),
BigDecimal(1122334455.66778899)
)
println(bigDecimals.sum());
// 2234556666.890011250972747802734375
sumBy() BigDecimal
sumByBigDecimal()
extension function will need a selector
.
fun <T> Iterable<T>.sumByBigDecimal(selector: (T) -> BigDecimal): BigDecimal {
var sum: BigDecimal = BigDecimal.ZERO
for (element in this) {
sum += selector(element)
}
return sum
}
Let’s run and check the result:
println(bigDecimals.sumByBigDecimal { it });
// 2234556666.890011250972747802734375
If you create a Foo
class with two fields: name
, value
.
This is how we use sum()
& sumByBigDecimal()
to work with List of Foo
objects.
val foos = listOf(
Foo("A", BigDecimal(124567890.0987654321)),
Foo("B", BigDecimal(987654321.123456789)),
Foo("C", BigDecimal(1122334455.66778899))
)
println(foos.map { it.value }.sum());
// 2234556666.890011250972747802734375
println(foos.sumByBigDecimal { it.value });
// 2234556666.890011250972747802734375
Conclusion
Today we’re learned how to use sum()
, sumBy()
, sumByDouble()
and sumByBigDecimal()
for List, List of Objects & Map.
Let me summarize all of them.
sum()
: works for almost simple List with number types, but needsmap()
function to work with List of custom Objects.sumBy()
: always returnsInt
value, hasselector
parameter so no need ofmap()
function.sumByDouble()
: likesumBy()
but always returnsDouble
value.BigDecimal
: Kotlin doesn’t support, need to createsum()
&sumByBigDecimal()
extension functions.
Thanks
Thanx for helping. This text document very helpfull.
when I tried adding the Iterable.sum() function, I was getting an error that it was expecting a type for the iterable.
I fixed it by doing the following
“`
fun Iterable.sum(): BigDecimal {
var sum: BigDecimal = BigDecimal.ZERO
for (element in this) {
sum += element
}
return sum
}
“`
Oh yeah, it’s just a typo because of syntax highlighter plugin which needs ‘<‘ for ‘<', I've fixed:
Thanks for your comment to notify me 🙂