Java 8 Functional Programming with Collect

Srikant Vavilapalli
2 min readDec 22, 2019

--

demystify streams, consumers and supplier

Let’s continue from where we left.

We will discuss collect in greater details.

Lets say you have a list of numbers :
List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9);

Let say you want to count number of elements in the list?

numbers.stream().collect(Collectors.counting());

Collect method performs a reduction operation by using Collector. It will output 9. You can use size operator on the collection to get size of collection. The above example is not useful for our user case. We will look into more concrete examples.

Before we process you should know Collect is a terminal operation.

You ask what’s a terminal operation

A terminal operation returns a non stream value such a primitive, collection or no value at all.

Let say you have a List of Employees and you are tasked with grouping employees by their city. How can we achieve this with streams. Well, Collectors has exactly what we are looking for a groupingBy method.

Collectors groupingBy

Let’s understand whats going on.

We have list of employees (age, city, eid) which we want to group by city. We use streams collect which Performs a mutable reduction operation on the elements of this stream using a Collector.

Arrays.asList(p1, p2, p3, p4).stream()
.collect(
Collectors.groupingBy(Employee::getCity)
);

We are group the employees list with city. It’s going to return a Map whose key is city which is of type String and value is a list of employees who live in that city. In short the return type is Map<String, List<Employee>>

Output:

{Elgin=[Employee@3d075dc0, Employee@214c265e], Schaumburg=[Employee@448139f0, Employee@7cca494b]}

Let say you don’t the whole Employee object, you just want their age.

You can do easily achieve this by below code

Map<String, List<Integer>> mapList2 = Arrays.asList(p1, p2, p3, p4).stream()
.collect(
Collectors.groupingBy(
Employee::getCity, Collectors.mapping(Employee::getAge, Collectors.toList())
)
);

Output:

{Elgin=[35, 30], Schaumburg=[35, 31]}

groupingBy takes an additional parameter which modified employee object to the desired object we want.

Let’s say you want average age of the employees from a given city? You can use a averagingInt from Collectors.

Let’s see it in action:

Map<String, Double> mapList2 = Arrays.asList(p1, p2, p3, p4).stream()
.collect(
Collectors.groupingBy(
Employee::getCity,
Collectors.averagingInt(Employee::getAge)
)
);

Output: {Elgin=32.5, Schaumburg=33.0}

What if you want find the total amount of salary paid in each city:

You can use reducing of Collectors to achieve what we are looking for.

Reducing accepts three parameters, the initial or default value, the mapper to retrieve the salary of Employee, the operation function is used to reduce the mapped values i.e Integer sum.

Map<String, Integer> mapList4 = 
Arrays.asList(p1, p2, p3, p4).stream().collect(
Collectors.groupingBy(
Employee::getCity,
Collectors.reducing(0, Employee::getSalary, Integer::sum)
)
);

Output: {Elgin=550000, Schaumburg=275000}

Hope this kind of helps you understand collect method.

--

--