Grouping, transforming and reduction with Java 8
Java, Java8 ·In this previous post, I wrote about how we can group collections of objects with streams and grouping. This is useful but does not cover specific use cases. For example, sometimes we do not only need to group things but also transform the result into a more appropriate object.
In this post, we will learn how to apply transformations and reduction to the groupingBy result.
Here you can view the source code of the following examples.
1 Grouping by and transform
Let’s take the model I used in the previous post where we had a collection of persons who owned a pet.
Now we want to know which pets belong to persons living in New York. We are asking for pets, so we can’t just make a grouping since we would be returning a collection of persons. What we need to do is group persons by city and then transform the stream to a collection of pets.
For this purpose, we use mapping on the result of the group by:
public void groupAndTransform(List<Person> persons) { final Map<String, List<Pet>> petsGroupedByCity = persons.stream().collect( groupingBy( Person::getCity, mapping(Person::getPet, toList()) ) ); System.out.println("Pets living in New York: " + petsGroupedByCity.get("NYC")); }
In the grouping phase, we group persons by city and then perform a mapping to get each person’s pet.
2 Grouping, transforming and reducing
The previous example is useful for converting groupings of objects, but maybe we don’t want to obtain the whole list for each group. In this example, we still want to group pets by its owner’s city, but this time we only want to get the oldest pet of each list.
The method collectingAndThen from Collectors allow us to make a final transformation to the result of the grouping:
public void groupTransformAndReduce(List<Person> persons) { final Map<String, Pet> olderPetOfEachCity = persons.stream().collect( groupingBy( Person::getCity, collectOlderPet() ) ); System.out.println("The older pet living in New York is: " + olderPetOfEachCity.get("NYC")); } private Collector<Person, ?, Pet> collectOlderPet() { return collectingAndThen( mapping( Person::getPet, Collectors.maxBy((pet1, pet2) -> Integer.compare(pet1.getAge(), pet2.getAge())) ), Optional::get); }
After we group persons by city, in collectingAndThen we are transforming each person in each city’s list to its pet, and then applying a reduction to get the pet with the highest age in the list.
3 Conclusion
Java 8 grouping, transforming and reduction can be accomplished with the Collectors API not only allow us to group collections of things but also make transformations and reductions to obtain different objects depending on our needs.
I’m publishing my new posts on Google plus and Twitter. Follow me if you want to be updated with new content.