A while ago I wrote a blog post Groovy Goodness: Getting the Sum of Items in a Collection. Today I presented about this little topic as part of the "Groovy Hidden Gems" session at Gr8Conf 2012. One of the attendees noticed the code where we calculate the sum of the Person
objects was not working. So it time to revisit this topic.
The problem with the presented solution is that with more than two elements in the list the code throws an exception. The return method of the plus()
method is a BigDecimal
so Groovy tries to invoke the plus()
method on the BigDecimal
class with a Person
type argument. And that doesn't exist, hence the exception.
To fix this we must return a new Product
object from the plus()
method with the sum of the price
property. The code is now:
class Product { String name BigDecimal price Product plus(Product other) { new Product(price: this.price + other.price) } } def products = [ new Product(name: 'laptop', price: 999), new Product(name: 'netbook', price: 395), new Product(name: 'iPad', price: 200) ] assert 1594 == products.sum().price
EDIT: I like to thank the people that wrote a comment. The current solution focuses on the implementation of a plus()
method in a class to get a sum value. But we can also use a closure for the sum()
. In the closure we define the property to calculate the sum for. Or we can use the optional spread operator to get the price property of all products and invoke the sum()
method.
assert products.sum { it.price } == 1594 assert products.price.sum() == 1594 assert products*.price.sum() == 1594