Tuesday, 28 June 2016

Java 8 Collectors Example (groupingBy, mapping, summingInt, toCollection, toList examples)

Stream Collectors Example in Java 8 : toList, toCollection, summingInt, groupingBy

The collect operation in stream is a handy terminal operation which is used to accumulate or convert a stream in to collections like List, Set Or Map.

It can be used to accumulate data present in a stream and convert into a list or a similar collection.
Similarly we can summarize data according to various criteria.

A collect operation is a combination of 4 elements namely supplier, an accumulator, a combiner and a finisher.
But since Java 8 uses inbuilt collectors, we do not need to implement one for most of our daily operations.


Here are a list of Methods explained below:
   1.   Collectors.toList()
   2.   Collectors.toCollection()
   3.   Collectors.summingInt()
   4.   Collectors.averagingDouble() and Collectors.averagingInt()
   5.   Collectors.groupingBy()


Lets the fun begin!!
We will create a List of Employee Objects to explain this tutorial.
The Employee class looks like this. It has a constructor and some getters and setters. Simple right?!!

package codermag.net.java8;

public class Employee {
 public String name;
 public int age;

 Employee(String name, int age) {
  this.setName(name);
  this.setAge(age);
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 @Override
 public String toString() {
  return getName();
 }
}


Now lets us look at the program below:


 List<Employee> employees = new ArrayList<Employee>();
  employees.add(new Employee("John", 35));
  employees.add(new Employee("Wendy", 43));
  employees.add(new Employee("Scott", 22));
  employees.add(new Employee("Joe", 17));
  employees.add(new Employee("Brad", 43));

  Stream<Employee> employeeStream = employees.stream();




1. Lets collect all the Employee Names and collect them in a List

The toList() operation in one of the basic operations of the Collectors class.
The toList() function in Collectors helps to convert a Stream to a List as shown below.

  // Accumulate names into a List
  List<String> listOfNames = employeeStream
                                   .map(Employee::getName)
                                   .collect(Collectors.toList());

System.out.println(listOfNames ); //[John, Wendy, Scott, Joe, Brad]




2. Lets filter names starting with the letter 'J'.


  // Filter names starting with 'J'
  List<String> listOfNamesStartingWithJ = employeeStream
                                              .filter(x -> x.getName().startsWith("J"))
                                              .map(Employee::getName)
                                              .collect(Collectors.toList());  

System.out.println(listOfNamesStartingWithJ); //[John, Joe]



3. Get the List of person objects whose name starts with 'J'.

For this case we are introducing an intermediate filter() method to filter data based on criteria.

List<Employee> listOfPersons = employeeStream
                                 .filter(x -> x.name.startsWith("J"))
                                 .collect(Collectors.toList());  

System.out.println(listOfPersons); //[John, Joe]




4. Lets sort the names using TreeSet.

A similar operation is toCollection() operation of Collectors class in Java 8.
Unlike the toList() Collector class, this is more generalized method for converting to collections.

  // Accumulate names into a TreeSet
  Set<String> setOfName = employeeStream
                                  .map(Employee::getName)
                                  .collect(Collectors.toCollection(TreeSet::new));

System.out.println(setOfName);  //[Brad, Joe, John, Scott, Wendy]




5. Get the sum of ages of all Employees.

Collectors in Java 8 are versatile and there are various utility methods which makes our
life much more simplier. For example the summingInt() of Collectors class in Java 8 lets you
calculate the sum of attributes of Stream data.

      int totalAge = employeeStream
                           .collect(Collectors.summingInt(Employee::getAge));
  
  System.out.println(totalAge); //10



6. Get the average of the ages of all employees.

Collectors class in Java 8 has functions like averagingDouble() and averagingInt()
to directly calculate the average of nummeric values.

Double averageAge=employeeStream
                        .collect(Collectors.averagingDouble(emp -> emp.age));
  
System.out.println(averageAge); // 32.0




7. Group by a particular attribute.

In java 8 Collectors, probably one of the most talked about method is the groupingBy() method.
The groupingBy() method in Collectors class in Java 8 lets you group data based on criterias set by you.
For example the following method uses the groupingBy() Collectors class method to group employees based
on their ages.

Map<Integer, List<Employee>> empMap = employeeStream
                                          .collect(Collectors.groupingBy(x -> x.age));

  empMap.forEach((age, empList) -> System.out.format(
    "Employees of age %s are : %s\n", age, empList));


/*
Employees of age 17 are : [Joe]
Employees of age 35 are : [John]
Employees of age 22 are : [Scott]
Employees of age 43 are : [Wendy, Brad]
*/