stream api in java 8

JAVA8 Stream API
The most powerful feature in Java8 is introducing Java.Util.Stream package.

By Steam API, We can do filter,map,reduce like operations on a collection . It is very useful as many times we need to filter a collection based on some criteria.
Like, find the Employee who has a salary greater than 20000.

In order to do these prior to Java8, we need to iterate over the collection then check each employee’s salary. If it is greater than 20000 we need to put it in an another list. Then print out that list. This is very time-consuming and unnecessary work for a developer.

But in Java8 we can do it on the fly. No need to do all those prior java8 stuff.
Now we have Stream interface you can invoke stream() function or parallelStream function on Collection to get Stream Interface.

In-Stream interface you can do multiple useful operations like filter the stream based on
Criteria to do that just need to pass a Java.util.function.Predicate which contains the filter criteria.

As java8 also support Lambda Expression you can pass the predicate as an argument of a method.

Please read my article on java lambda Expression to know about this

Enough theory lets do some coding

Suppose I want to filter Employees  of a company based on their salary,department,sex,manager

By Java8 we do it very easily by using filter Operation

Step 1:
Create an Employee class

package com.example.java;

public class Employee {
           
            String name;
            String sex;
            boolean manager;
            Integer salary;
            String dept;
           
            public String getName() {
                        return name;
            }
            public void setName(String name) {
                        this.name = name;
            }
            public String getSex() {
                        return sex;
            }
            public void setSex(String sex) {
                        this.sex = sex;
            }
            public boolean isManager() {
                        return manager;
            }
            public void setManager(boolean manager) {
                        this.manager = manager;
            }
            public Integer getSalary() {
                        return salary;
            }
            public void setSalary(Integer salary) {
                        this.salary = salary;
            }
            public String getDept() {
                        return dept;
            }
            public void setDept(String dept) {
                        this.dept = dept;
            }
            @Override
            public String toString() {
                        return "Employee [name=" + name + ", sex=" + sex + ", manager="
                                                + manager + ", salary=" + salary + ", dept=" + dept + "]";
            }
           
           
           
           
           
           

}


Step 2:

Create another class which will perform filtering operation on Employee list

package com.example.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;

import com.example.java.Employee;

public class EmployeeUtiltyStream {
           

           
            List<Employee> list = new ArrayList<Employee>();
           
            public EmployeeUtiltyStream()
            {
                        init();
                       
            }
           
            private void init()
            {
                        Employee emp = new Employee();
                        emp.setName("Shamik Mitra");
                        emp.setManager(false);
                        emp.setSex("Male");
                        emp.setSalary(20000);
                        emp.setDept("Java");
                       
                        Employee emp1 = new Employee();
                        emp1.setName("Aman Verma");
                        emp1.setManager(true);
                        emp1.setSex("Male");
                        emp1.setSalary(50000);
                        emp1.setDept("IOT");
                       
                        Employee emp2 = new Employee();
                        emp2.setName("Priti Dey");
                        emp2.setManager(true);
                        emp2.setSex("FeMale");
                        emp2.setSalary(40000);
                        emp2.setDept("Mainframe");
                       
                        Employee emp3 = new Employee();
                        emp3.setName("Ajay Ghosh");
                        emp3.setManager(false);
                        emp3.setSex("Male");
                        emp3.setSalary(30000);
                        emp3.setDept("Java");
                       
                        list.add(emp);
                        list.add(emp1);
                        list.add(emp2);
                        list.add(emp3);
            }
           
            public void filterList(Predicate<Employee> predicate) {
                         
                        Stream<Employee> employeeStream = list.parallelStream();
                       
                        Stream<Employee> filteredEmployeeStream = employeeStream.filter(predicate);
                       
                        filteredEmployeeStream.forEach(employee->System.out.println(employee));
                       
            }
           
           
           
            public static void main(String[] args) {
                       
                        EmployeeUtiltyStream employeeUtiltyStream = new EmployeeUtiltyStream();
                       
                        employeeUtiltyStream.filterList(employee->employee.getSalary()<=40000);
                        System.out.println("****************************************");
                        employeeUtiltyStream.filterList( employee->employee.getSex().equalsIgnoreCase("FeMale"));
                        System.out.println("****************************************");
                        employeeUtiltyStream.filterList( employee->employee.isManager());
                        System.out.println("****************************************");
                        employeeUtiltyStream.filterList( employee->employee.getDept().equalsIgnoreCase("Java"));
                       
                       
                       
            }

}



Please look this class very carefully
I create a init method where I add Employees in a List.

Then I create a method call filterList which takes a java.util.function.Predicate class as argument

public void filterList(Predicate<Employee> predicate) {
                         
                        Stream<Employee> employeeStream = list.parallelStream();
                       
                        Stream<Employee> filteredEmployeeStream = employeeStream.filter(predicate);
                       
                        filteredEmployeeStream.forEach(employee->System.out.println(employee));
                       
            }


To get Stream class, I invoke parallelStram method on employee list.
Then call filter method and pass the predicate.

Now look at main method

employeeUtiltyStream.filterList(employee->employee.getSalary()<=40000);

here I invoke filterList method and pass Predicate using a lambda expression
in Predicate I say filter employee based on a salary less than 40,000

guess what output is

Employee [name=Shamik Mitra, sex=Male, manager=false, salary=20000, dept=Java]
Employee [name=Ajay Ghosh, sex=Male, manager=false, salary=30000, dept=Java]
Employee [name=Priti Dey, sex=FeMale, manager=true, salary=40000, dept=Mainframe]
****************************************
Employee [name=Priti Dey, sex=FeMale, manager=true, salary=40000, dept=Mainframe]
****************************************
Employee [name=Priti Dey, sex=FeMale, manager=true, salary=40000, dept=Mainframe]
Employee [name=Aman Verma, sex=Male, manager=true, salary=50000, dept=IOT]
****************************************
Employee [name=Ajay Ghosh, sex=Male, manager=false, salary=30000, dept=Java]

Employee [name=Shamik Mitra, sex=Male, manager=false, salary=20000, dept=Java]

Anonymous Function in java 8 using lambda



Java8 Lambda Expression


In this article, we will discuss Java8 most debated feature Lambda Expression.

What is a Lambda Expression?

In brief, I can say Lambda Expression is the way of passing functions into a function. Where Passing function is being used by the function where it  passed.

Passing function act as a Callback function.

In Java 8 Version Java adopts the Lambda expression actually this is the first step towards functional programming. In functional programming, we can pass a function in another function that is called Higher Order Function.

The benefits of this are Lambda Expression is
As you can pass a function into an another function or I can say you can pass behavior into a function (think function as a behavior). So It is on caller's hand what behavior you can want to do or I can say the strategy is on caller’s hand so it can be altered easily. Prior to this If you want to pass a behavior probably you will create an anonymous class and wrap that behavior in that class and pass it to the another method.

To be specific prior to Lambda expression we will solve this problem that is passing behavior into a method by anonymous class.

Think about Thread and Runnable interface. In Runnable interface there is a run method where we define the behavior or the set activities which should be executed when a thread is spawned.

And we pass this in Thread constructor so when Thread is in running state it performs the activity written in Runnable. But to do we have to create an anonymous class and override public void run then pass it in Thread class.

This not right way to pass a function rather what we did we pass an object where the function is in wrapped form.

Java8 try to get rid of this now no need to create that class directly you can pass a method body to a method.

Let’s take an Example

Suppose I need to compute an Area of Circle and Rectangle and print them so How to do it by lambda Expression.

First I create two functional interfaces, It just a Java interface and it has one method where I specify the behavior template method.

package com.example.java;

public interface Shape {
           
            public int execute(int a,int b);

}


package com.example.java;

public interface Print {
           
            public  void print(int value);

}


Now I create a Class where we define Rectangle and Circle compute behavior and print behavior by Lambda Expression


package com.example.impl;

import com.example.java.Print;
import com.example.java.Shape;

public class ShapeClosure {

           
           
            public void computeArea(Shape shape,Print print,int length,int breadth)
            {
                        int result = shape.execute(length, breadth);                   
                        print.print(result);
            }
           
            public static void main(String[] args) {
                       
                        ShapeClosure closure = new ShapeClosure();
                        Shape circle = (a,b)->(int)3.14f*a*b;                     
                        Print area = (result)->System.out.println("Area of Circle " + result);
                       
                        closure.computeArea((a,b)->a*b, (result)->System.out.println("Area of Rectangle " + result), 10, 20);
                        closure.computeArea(circle, area, 10, 5);


                       
                       
            }
}

Look at the  ShapeClosure class here I create a ComputeArea Function, the function which will take Shape and Print function as a callback function. In order to do that
Look at the ComputeArea function arguments, it takes shape and Prints functional interface as the argument. Because this functional interface says about the behavior of the function

Shape interface behavior is executed which takes two int argument and return an int
Print interface behavior is print which takes an int argument and prints the value.

In computing are we call this behavior or another way I can say in a function I use callback function's behavior which is the main motto of functional programming


Now look these lines in the main method

Shape circle = (a,b)->(int)3.14f*a*b;                     
                        Print area = (result)->System.out.println("Area of Circle " + result);
                       
                        closure.computeArea((a,b)->a*b, (result)->System.out.println("Area of Rectangle " + result), 10, 20);
                        closure.computeArea(circle, area, 10, 5);


Here I use Lambda expression as shape’s execute method takes two int’s and compute them so
(a,b)->(int)3.14f*a*b;          

Two arguments int a and b (Don’t need to say data type from functional interface java takes the argument type.)

Now define the body of executing as (int)3.14f*a*b;

So these line is (a,b)->(int)3.14f*a*b;

Is equivalent to

public int execute(int a,int b)
{
  return (int)3.14f*a*b;
}


Same for print , I pass them in computeArea along with data’s which is main intent of functional programming

closure.computeArea(circle, area, 10, 5);


On another way, I can directly pass them in computeArea like this

                        closure.computeArea((a,b)->a*b, (result)->System.out.println("Area of Rectangle " + result), 10, 20);


when you run the program. You will see Output

Area of Rectangle 200
Area of Circle 150