Ted Vinke

About Ted Vinke

Ted is a Java software engineer with a passion for Web development and JVM languages and works for First8, a Java Web development company in the Netherlands.

Java 8 Lambdas vs Groovy Closures Compactness: Grouping And Summing

Java 8 is featuring lambdas, which are similar to a construction Groovy has already for some time: closures.

In Groovy we could already do this:
 
 
 
 
 
 
 

def list = ['a', 'b', 'c']
print list.collect { it.toUpperCase() }
// [A, B, C]

where { it.toUpperCase() } is the closure.

In Java 8 we can achieve the same functionality now in a concise way.

list.stream().map( s -> s.toUpperCase() )

Although you could argue that with proper use of the new Stream API, bulk operations and method references, at least the intent of a piece of code is conveyed more clearly now – Java’s verboseness can still cause sore eyes.

DukeGroovyChair

Here are some other examples.

Some Groovy animals

class Animal {
    String name
    BigDecimal price
    String farmer
    String toString() { name }
}

def animals = []
animals << new Animal(name: "Buttercup", price: 2, farmer: "john")
animals << new Animal(name: "Carmella", price: 5, farmer: "dick")
animals << new Animal(name: "Cinnamon", price: 2, farmer: "dick")

 

Example 1: Summing the total price of all animals

Groovy

assert 9 == animals.sum { it.price }
// or animals.price.sum()

What Groovy you see here:

  • sum can be called on a List and optionally passed a closure defining the property of “it” – the animal being iterated over – to sort on.
  • or sum can be called on a List without any arguments, which is equivalent to invoking the “plus” method on all items in the collection.

Java 8

Optional<BigDecimal> sum =
	animals.
		stream().
		map(Animal::getPrice).
		reduce((l, r) -> l.add(r));
assert BigDecimal.valueOf(9) == sum.get();

What Java you see here:

  • Through the Stream API’s stream method we can create a pipeline of operations, such as map and reduce
  • The argument to the map operation is a method reference to the getPrice() method of the currently iterated animal. We could also replace this part with the expression a -> a.getPrice()
  • reduce is a general reduction operation (also called a fold) in which the BigDecimals of the prices are added up. This is also giving us an Optional with the total sum.
  • BTW, if we were to use a double for price – which we don’t because I want to give a good example – we could have used an existing DoubleStream with a sum() on it e.g.
    double sum = animals.stream().mapToDouble(Animal::getPrice).sum();

 

Example 2: Grouping all animals by farmer

Groovy

def animalsByFarmer = animals.groupBy { it.farmer }
// [john:[Buttercup], dick:[Carmella, Cinnamon]]

Java 8

Map<String, List<Animal>> animalsByFarmer =
	animals
		.stream()
		.collect(
			Collectors.groupingBy(Animal::getFarmer));
// {dick=[Carmella, Cinnamon], john=[Buttercup]}

 

Example 3: Summing the total price of all animals grouped by farmer

Groovy

def totalPriceByFarmer =
    animals
        .groupBy { it.farmer }
        .collectEntries { k, v -> [k, v.price.sum()] }
// [john:2, dick:7]

What Groovy you see here:

  • collectEntries iterates through the “groupBy” map transforming each map entry using the k, v -> ... closure returning a map of the transformed entries. v.price is actually a List of prices (per farmer) – such as in example 1 – on which we can call sum().

Java 8

Map<String, BigDecimal> totalPriceByFarmer =
	animals
		.stream()
		.collect(
			Collectors.groupingBy(
				Animal::getFarmer,
				Collectors.reducing(
					BigDecimal.ZERO,
					Animal::getPrice,
					BigDecimal::add)));
// {dick=7, john=2}

This Java code again yields the same results. Since IDE’s, Eclipse at least, don’t format this properly, you’ll have to indent these kinds of constructions for readability a bit yourself.

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You'll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You'll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

Leave a Reply


9 × = nine



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close