Sunday, April 7, 2019

Consumer and BiConsumer Functional Interface - JAVA 8


Consumer and BiConsumer Functional Interface


Consumer<T> is an in-built functional interface introduced in Java 8 in the java.util.function package. It can be used in all contexts where an object needs to be consumed, i.e. taken as input, and some operation is to be performed on the object without returning any result.
Common example of such an operation is printing where an object is taken as input to the printing function and the value of the object is printed.

The functional method of Consumer is accept(T t).
@FunctionalInterface
Public interface Consume<T, > { …}

Here is a simple source code of java.util.function.Consumer
package java.util.function;
    
import java.util.Objects;
    
@FunctionalInterface
public interface Function<T> {
    public void accept(T t);
  }

Where accept (T t) is an abstract method where T is the type of the input to the Function.

Example 1:

import java.util.function.Consumer;

public class ConsumerExample {

       public static void main(String[] args) {

             // Calling Consumer Functional Interface without using Lambda Expression
             SendNotification notification = new SendNotification();
             notification.accept("Abdul");

             // Using Lambda Expression
             Consumer<String> consumer = username -> System.out.println("Send mail notification to : " + username);
             consumer.accept("Waheed");
       }
}

class SendNotification implements Consumer<String> {

       @Override
       public void accept(String user) {
             System.out.println("Send mail notification to : " + user);
       }
}

Output:
Send mail notification to : Abdul
Send mail notification to : Waheed



Example 2:
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class ConsumerExample2 {

       public static void main(String[] args) {

             ConsumerExample2 consumerExample2 = new ConsumerExample2();

             Consumer<Student> consumer = student -> {
                    System.out.println("Name: " + student.getName());
                    System.out.println("Age: " + student.getAge());
                    System.out.println("================================");
             };

             List<Student> students = consumerExample2.populateStudentList();
             for (Student student : students) {
                    consumer.accept(student);
             }
       }

       public List<Student> populateStudentList() {
             List<Student> studentList = Arrays.asList(new Student("Abdul", 31), new Student("Waheed", 29),
                           new Student("DummyUser", 20), new Student("Adam", 25));
             return studentList;
       }
}

class Student {
       private String name;
       private int age;

       public Student(String name, int age) {
             super();
             this.name = name;
             this.age = 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;
       }

       public boolean equals(Object obj) {
             Student student = (Student) obj;
             if ((this.getName().equals(student.getName()) && this.getAge() == student.getAge())) {
                    return true;
             } else {
                    return false;
             }
       }
}

Output:
Name: Abdul
Age: 31
================================
Name: Waheed
Age: 29
================================
Name: DummyUser
Age: 20
================================
Name: Adam
Age: 25
================================

Example 3:

In this example, I’ll use Predicate, Function and Consumer for better understanding. Below Program will print Student detail with its grade (Generate Grade based on marks) who marks are greater than 60%.

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Function;

/**
 * Use of Predicate, Function and Consumer Functional Interface in one class;
 *
 * It will print name of the student who has marks greater than 60% with its
 * GRADE.
 *
 * @author Abdul Waheed
 *
 */
public class ConsumerExample3 {

       public static void main(String[] args) {

             ConsumerExample3 consumerExample3 = new ConsumerExample3();

             Predicate<Stud> p1 = student -> student.getMarks() > 60;

             Function<Stud, String> f1 = student -> {
                    int marks = student.getMarks();

                    if (marks > 80) {
                           return "A";
                    } else if (marks > 70) {
                           return "B";
                    } else if (marks > 60) {
                           return "C";
                    } else {
                           return "E";
                    }
             };

             // Internally invoking Function interface
             Consumer<Stud> c1 = student -> {
                    System.out.println("Name: " + student.getName());
                    System.out.println("Marks: " + student.getMarks());
                    System.out.println("Grade: " + f1.apply(student));
                    System.out.println("================================");
             };

             List<Stud> students = consumerExample3.populateStudentList();
             for (Stud stud : students) {
                    if (p1.test(stud)) {
                           c1.accept(stud);
                    }
             }
       }

       public List<Stud> populateStudentList() {
             List<Stud> studentList = Arrays.asList(new Stud("Abdul", 31, 60), new Stud("Waheed", 29, 90),
                           new Stud("DummyUser", 20, 80), new Stud("Adam", 25, 47));
             return studentList;
       }
}

class Stud {
       private String name;
       private int age;
       private int marks;

       public Stud(String name, int age, int marks) {
             super();
             this.name = name;
             this.age = age;
             this.marks = marks;
       }

       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;
       }

       public int getMarks() {
             return marks;
       }

       public void setMarks(int marks) {
             this.marks = marks;
       }

       public boolean equals(Object obj) {
             Student student = (Student) obj;
             if ((this.getName().equals(student.getName()) && this.getAge() == student.getAge())) {
                    return true;
             } else {
                    return false;
             }
       }
}

Output:

Name: Waheed
Marks: 90
Grade: A
================================
Name: DummyUser
Marks: 80
Grade: B
================================

  



Apart from accept (T t) method, Consumer also has only one default method.

Modifier and Type
Method and Description
default Consumer<T>
andThen(Consumer<? super T> after)
Returns a composed Consumer that performs, in sequence, this operation followed by the after operation.


We can use andThen(Consumer<? super T> after) for Consumer Chaining i.e. we can call multiple Consumer Function at the same time.

C1.andThen(C2).andThen(C3).accept(“Student);

Over here, first C1 will be called then C2 and then C3.

Let’s understand with an example where if a new student register to a website, then data should be updated to database and send welcome mail to User as well.


Example 3:

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class ConsumerChainning {

       public static void main(String[] args) {

             ConsumerChainning chainning = new ConsumerChainning();

             Consumer<Student> addToDB = Student -> {
                    System.out.println("Open Database Connection");
                    System.out.println("Write Record to DB");
                    System.out.println("Name: " + Student.getName() + ", Age: " + Student.getAge());
                    System.out.println("Close Connection");
                    System.out.println("================================");
             };

             Consumer<Student> sendMail = Student -> {
                    System.out.println("Configure Mail Server");
                    System.out.println("Send Mail to user " + Student.getName());
                    System.out.println("================================\n");
             };

             List<Student> students = chainning.populateStudentList();
             for (Student student : students) {
                    addToDB.andThen(sendMail).accept(student);
             }
       }

       public List<Student> populateStudentList() {
             List<Student> studentList = Arrays.asList(new Student("Abdul", 31), new Student("Waheed", 29),
                           new Student("DummyUser", 20), new Student("Adam", 25));
             return studentList;
       }

}

Output:

Open Database Connection
Write Record to DB
Name: Abdul, Age: 31
Close Connection
================================
Configure Mail Server
Send Mail to user Abdul
================================

Open Database Connection
Write Record to DB
Name: Waheed, Age: 29
Close Connection
================================
Configure Mail Server
Send Mail to user Waheed
================================

Open Database Connection
Write Record to DB
Name: DummyUser, Age: 20
Close Connection
================================
Configure Mail Server
Send Mail to user DummyUser
================================

Open Database Connection
Write Record to DB
Name: Adam, Age: 25
Close Connection
================================
Configure Mail Server
Send Mail to user Adam
================================

 BiConsumer Functional Interface


It is very similar to Consumer Functional Interface. The only difference is just that it will accept two input arguments instead of one and will return nothing

@FunctionalInterface
public interface BiConsumer<T,U> {
            accept(T t, U u);
}


Let’s see an example

Example 4:

import java.util.function.BiConsumer;

public class BiConsumerExample {

       public static void main(String[] args) {

             BiConsumer<String, String> fullName = (fn, ln) -> System.out.println(fn.concat(" " + ln));

             fullName.accept("Abdul", "Waheed");
       }
}
 Output:
Abdul Waheed 

That’s it for Consumer and BiConsumer Functional Interface, Will talk about other Predefined Functional Interface in my next blog.

Happy Coding…!!!

How TOPT Works: Generating OTPs Without Internet Connection

Introduction Have you ever wondered how authentication apps like RSA Authenticator generate One-Time Passwords (OTPs) without requiring an i...