{{announcement.body}}
{{announcement.title}}

Refactoring Java 8 Code With Collector

DZone 's Guide to

Refactoring Java 8 Code With Collector

I'm going to refactor code based on Java 7 to Java 8 using the functional components, specifically Collector. The plan is simple, learn it by coding it.

· Java Zone ·
Free Resource

I am planning to refactor a code that is based on Java 7 to Java 8 using the functional components, specifically Collector. The plan is simple: learn it by coding it. Let’s get started…

Overview of the Java Object We Are Dealing With

Java object to refactor


The following code is intended to fetch a few specific pieces of data from the Company object, where the company has a list of employees. I would like to perform the following operations:

  • Find out the most common name (Employee name) in the company.
  • Find the highest salaried employee of the company.
  • Find the sum of salaries for all men.
  • Find the most popular grade/band in the company.

Prior to Java 8, it was tough to refactor this logic and find out some common parts. But functional components make refactoring easy.

Pre-Java 8 Version

Let’s go through the code,

Find out the most common employee name in the company

Java


Find the highest salaried employee

Java


Find the sum of salaries for all Men

Java


Find the most popular grade/band in the company

Java


In all the cases, we need to iterate through various departments and then employees. But since the conditions and the data we want to collect are in a different format, we won't be able to find something common and refactor it properly. Let’s see how Java 8 deals with this.


As an initial step, let's use streams and do the processing.

Find out the most common employee name in the company

Let’s go through the logic of nameAndCount, since the iterations (for loop on department and employee) have a defined result(nameAndCount). We can use streams to get that value:

Java


Why didn’t we get the result via collect? We have some logic there. We need to identify the duplicates. The value of the map is the count of employee names. Let’s see the final results.

Java


Find the highest salaried employee

Let’s do the same refactoring here as well. But here, we can use collect as the logic is fairly less complex.

Java


Find the sum of salaries for all Men

Well, this one seems much simpler.

Java


Find the most popular grade/band in the company

We need to apply a similar logic as we did for the first method. (I mean findMostRepeatingNameInCompany.) Let's try it.

Java


We have some common values and might be able to save some lines if we find those common things and refactor it properly, let's go with that…


This time, let's use stream.collect() method everywhere. So we have changes only on two method calls, findMostRepeatingNameInCompany and findMostPopularBandInCompany.

Find out the most common employee name in the company

Let’s try to use collect here, and avoid the addToNameAndCountMap method call. If we use the right collector, we can collect data to a map, with a custom key or value. We are going to use Collectors.groupingBy(Employee::getName,Collectors.counting()) for this.

Java


Find the most popular grade/band in the company

Let’s do the same thing here as well.

Java


Now we have a common pattern, and it seems there are possibilities to extract some functional components out of it. Let’s explore that possibility.


We could see that the methods findMostRepeatingNameInCompany, findEmployeeWithHighestSalaryInTheCompany and findMostPopularBandInCompany follows a similar pattern. The only difference is the type of map and the collector we use. So, let's write a method that returns a generic map and accept a collector.

Java


This is a generic method, it works for different inputs, if T is a string, it will use the collector to get a Map<String, Long> as the return type. If we use another object, say, Employee, then the return type will be Map<Employee, Long>. Let’s try using this method call in the next three methods.

Find out the most common employee name in the company

Java


Find the highest salaried employee

Let’s do the same refactoring here as well:

Java


Find the most popular grade/band in the company

Java


Find the sum of salaries for all men

Well, we need a different way here, as this one is completely different from the rest of the methods.

Java


Well, we have used the functional components and achieved a better reusable code, but still, this can be cleaned up a bit.


You might have noticed that all these methods need a single value in return, not a list. And, we use optional and some logic to identify that single element. Can we extract that too, let’s try that now.

Java


This method returns the key of the biggest param in a map, using generics, this one can be applied to all of our methods

Find out the most common employee name in the company

Java


that simple? yes, it is

Find the highest salaried employee

Java


Find the most popular grade/band in the company

Java


Done? No, we are not done yet… there is a bit more to do.


In the methods findMostRepeatingNameInCompany, findEmployeeWithHighestSalaryInTheCompany, and findMostPopularBandInCompany, there is still a repeating pattern, we use processEmployeeToMap, and immediately, we call fetchParamsFromMap. Let’s combine it.

Java


Now, let’s see how our will methods look:

Find out the most common employee name in the company

Java


Find the highest salaried employee

Java


Find the most popular grade/band in the company

Java


We can even continue to simplify this, we can put the collectors outside and the parent calls can pass the collection, and then we don’t really need this method calls itself.

All code is available on GitHub, and each separate iteration is in a separate commit, please check this out at https://github.com/surajcm/java_fun_extraction_01/commits/master.

Topics:
collector, functional programming, java 7, java 8, tutorial

Published at DZone with permission of Suraj Muraleedharan . See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}