Wednesday, March 22, 2023

Functional Interface in Java

 Any interface with a SAM(Single Abstract Method) is a functional interface. It can have other static or default methods. 

public interface Testable {

    void printName(String name);

}

There are five ways of implementing this Single Abstract Method:

1. Using normal function inside the implementation class

class Child implements Testable{

    void printName(String name) {

        System.out.println("Hi " + name);

    }

}   

new Child().printName("Tester");

2. Using anonymous class to override

Anonymous class can extend or implement only one class/interface.

class Test {

    Testable obj = new Testable() {           

        void printName(String name) {

            System.out.println("Hi " + name);

        }

    };

    obj.printName("Tester");  // Parent object

 

3. Using lambda operator

class Test {

    Testable obj = (name) -> {System.out.println("Hi " + name)

// method name skipped since only one method

    obj.printName("Tester"); 

}   

4. Using method reference

Method reference can be used if lambda just calls one method.

class Test {

    Testable obj = System.out::println // Cannot print Hi // Skipping arguments

    obj.printName("Tester"); 

}

Method reference is of 3 types:

For calling Child's static method,

Testable obj = Child::print;      obj.printName("Tester"); 

For calling Child's non-static method,

Testable obj = new Child()::print;      obj.printName("Tester"); 

For calling Child's constructor,

Testable obj = Child::new;      obj.printName("Tester"); 


5. Using Built-in Functional Interfaces

Built-in Function interfaces are needed if the argument passed and the value returned are different, or if more than one argument needs to be passed.

Function

Function<Student,String> f = s->"Name:"+s.name +" and Age:"+s.age;

String str = f.apply(student) //Student object passed, String returned

BiFunction

BiFunction<Integer, Integer, Integer> bf = Arithmetic::add;  

int result = bf.apply(10, 20);  // Two integers passed, one Integer returned

Consumer

Consumer<String> c = System.out::println;

c.apply("Test"); // String passed, nothing returned.

There are also other variants of the Consumer — DoubleConsumer, IntConsumer, and LongConsumer. 

BiConsumer

Consumer<String,Integer> c = (name,age)->System.out.println("Name is "+name+" Age is "+age);

c.apply("Joe",12); // String and Integer passed, nothing returned.

Predicate

Predicate<String> p = (value) -> value != null;

p.apply("Test"); // String passed, boolean returned.

There are also other variants of the Predicate — DoublePredicate, IntPredicate, and LongPredicate. 

BiPredicate

BiPredicate<Integer,Integer> bp = (age,min)->age>=min;

bp.apply(22,18); // Two Integers passed, boolean returned.

Supplier

Supplier<String> s = ()->System.out.println("Hi");

s.apply("Test"); // Nothing passed, String returned.

There are also other variants of the Supplier — DoubleSupplier, IntSupplier, and LongSupplier. 


Other Built-in Java Functional Interfaces

Runnable –> This interface only contains the run() method.

Comparable –> This interface only contains the compareTo() method which can be overridden as 

Comparator<Book> byAuthor = (b1, b2) -> b1.getAuthor().compareTo(b2.getAuthor());

ActionListener –> This interface only contains the actionPerformed() method.

Callable -> This interface only contains the call() method.

No comments: