Java Course

An interface which contains only one abstract method but can have multiple default and static method is called Functional Interface.
Example
- Runnable -> It contains only run() method.
- Callable -> It contains only call() method.
- Comparable -> It contains only compareTo() method.
- Comparator-> It contains only compare() method.
Functional interface can have java.lang.Object methods.
Inside functional interface in addition to single Abstract method (SAM) we write any number of default and static methods.
@FunctionalInterface public interface MyInterface{ public void method1(); public boolean equals(Object o); }
This will not throw a compilation error as functional interface can have java.lang.Object methods.
@FunctionalInterface public interface FuctionalInterfaceExample { void m1(); default void m2() { System.out.println("Default method1"); } default void m3() { System.out.println("Default method2"); } static void m4() { System.out.println("Static method1"); } }
Function
- Functions are exactly same as predicates except that functions can return any type of result but function should (can) return only one value and that value can be any type as per our requirement.
- To implement functions oracle people introduced Function interface in 1.8version.
- Function interface present in Java.util.function package.
- Functional interface contains only one method i.e.. apply()
interface Function<T, R> { R apply(T t); }
Let's see an example, Write a function to find length of given input string.
import java.util.function.Function; public class FunctionTest { public static void main(String[] args) { Function<String, Integer> f = s -> s.length(); System.out.println(f.apply("Praveen")); System.out.println(f.apply("Oruganti")); } }
Output
7 8
Let's see another example
import java.util.function.Function; public class FunctionDemo { public static void main(String args[]) { beforeJava8();// Without Function Functional Interface fromJava8();// With Function Functional Interface } private static void beforeJava8() { Integer usd = 10; Double inrValue = convertUsdToInr(usd); System.out.println("From beforeJava8 " + usd + " USD = " + inrValue + " INR"); } // User defined method, this functionality is common in most of the Java // application private static Double convertUsdToInr(Integer usd) {// Single input Double inrRate = 71.0; // Call Webservice return usd * inrRate; } private static void fromJava8() { Double inrRate = 71.0; // Call Webservice Function<Integer, Double> function = usd -> usd * inrRate; System.out.println("From fromJava8 " + 10 + " USD = " + function.apply(10) + " INR"); // Function<T, R> // @param <T> the type of the input to the function // @param <R> the type of the result of the function } }
Output
From beforeJava8 10 USD = 710.0 INR From fromJava8 10 USD = 710.0 INR
Another Example using Function
import java.util.function.Function; public class FunctionDemo1 { public static void main(String args[]) { beforeJava8();// Without Function Functional Interface fromJava8();// With Function Functional Interface } private static void beforeJava8() { Integer n1 = 5; Integer squareOfNumber = calculateSquareOfNumber(n1); System.out.println("From withoutFunction – Square of a number is :" + squareOfNumber); } // User defined method, this functionality is common in most of the Java private static Integer calculateSquareOfNumber(Integer n1) { return n1 * n1; } private static void fromJava8() { Function<Integer, Integer> function = n1 -> n1 * n1; System.out.println("From withFunction – Square of a number is :" + function.apply(5)); // Function<T, R> // @param <T> the type of the input to the function // @param <R> the type of the result of the function } }
Output
From withoutFunction – Square of a number is :25 From withFunction – Square of a number is :25
Example using andThen
import java.util.function.Function; public class FunctionAndThenDemo { public static void main(String args[]) { Function<String, String> function1 = s -> s.toUpperCase(); Function<String, String> function2 = s -> s + " World"; System.out.println("Output of function1 : " + function1.apply("Hello")); System.out.println("andThen Output : " + function1.andThen(function2).apply("Hello")); //The output of the first function will become input to the second function //System.out.println("andThen Output 2 : " + function2.andThen(function1).apply("Hello")); } }
Output
Output of function1 : HELLO andThen Output : HELLO World
Another Example using andThen
import java.util.function.Function; public class FunctionAndThenDemo2 { public static void main(String args[]) { Function<Integer, Integer> function1 = n1 -> n1 + n1; Function<Integer, Integer> function2 = n1 -> n1 * n1; System.out.println("Function 1 andThen Function 2 : " + function1.andThen(function2).apply(10)); } }
Output
Function 1 andThen Function 2 : 400
Example using compose
import java.util.function.Function; public class FunctionComposeDemo { public static void main(String args[]) { Function<String, String> function1 = s -> s.toUpperCase(); Function<String, String> function2 = s -> s + " World"; System.out.println("Output – function1 : " + function1.apply("Hello")); System.out.println("Output – Compose : " + function1.compose(function2).apply("Hello")); // The output of the first function will become input to the second function } }
Output
Output – function1 : HELLO Output – Compose : HELLO WORLD
Another Example using compose
import java.util.function.Function; public class FunctionComposeDemo2 { public static void main(String args[]) { Function<Integer, Integer> function1 = n1 -> n1 + n1; Function<Integer, Integer> function2 = n1 -> n1 * n1; System.out.println("Function 1 compose Function 2 : " + function1.compose(function2).apply(10)); } }
Output
Function 1 compose Function 2 : 200
Example using Identity
import java.util.function.Function; public class FunctionIdentityDemo { public static void main(String args[]) { Function<String, String> function = Function.identity(); System.out.println(function.apply("Java8")); Function<Boolean, Boolean> function2 = Function.identity(); System.out.println(function2.apply(true)); Function<Integer, Integer> function1 = Function.identity(); System.out.println(function1.apply(1)); } }
Output
Java8 true 1
Let's see an example where a function can accept two arguments
import java.util.function.BiFunction; public class BiFunctionIdentityDemo { public static void main(String args[]) { BiFunction<Integer, Integer, Integer> sum = (x,y) -> (x+y); System.out.println(sum.apply(5,6)); } }
Predicate
- A predicate is a function with a single argument and returns boolean value.
- To implement predicate functions in Java, Oracle people introduced Predicate interface in 1.8 version (i.e.,Predicate<T>).
- Predicate interface present in Java.util.function package.
- It's a functional interface and it contains only one method i.e., test()
interface Predicate<T> { public boolean test(T t); }
As predicate is a functional interface and hence it can refers lambda expression
Almost all java applications has a requirement of checking whether condition is true or false, this is a common requirement. For this we can use Predicate function provided by Java.
import java.util.function.Predicate; public class PredicateDemo { public static void main(String args[]) { withoutPredicate(); withPredicate(); } private static void withoutPredicate() { System.out.println("From withoutPredicate"); Integer transactionAmount = 20000; if (isGreater(transactionAmount)) { System.out.println("Transaction Amount can't be greater than 10000"); } else { System.out.println("Transaction Amount is less than 10000, please proceed"); } } public static Boolean isGreater(Integer i) { if (i > 10000) { return true; } else { return false; } } private static void withPredicate() { System.out.println("From withPredicate!"); Integer amount = 20000; Predicate<Integer> p = transactionAmount -> transactionAmount > 10000; if (p.test(amount)) { System.out.println("Transaction Amount can't be greater than 10000"); } else { System.out.println("Transaction Amount is less than 10000, please proceed"); } } }
Output
From withoutPredicate Transaction Amount can't be greater than 10000 From withPredicate! Transaction Amount can't be greater than 10000
Predicate joining
It's possible to join predicates into a single predicate by using the following methods.
and()
or()
negate()
these are exactly same as logical AND ,OR complement operators
For example,
import java.util.function.Predicate; public class PredicateJoiningTest { public static void main(String[] args) { int[] x = { 0, 5, 10, 15, 20, 25, 30 }; Predicate<Integer> p1 = i -> i > 10; Predicate<Integer> p2 = i -> i % 2 == 0; System.out.println("The Numbers Greater Than 10:"); m1(p1, x); System.out.println("The Even Numbers Are:"); m1(p2, x); System.out.println("The Numbers Not Greater Than 10:"); m1(p1.negate(), x); System.out.println("The Numbers Greater Than 10 And Even Are:"); m1(p1.and(p2), x); System.out.println("The Numbers Greater Than 10 OR Even:"); m1(p1.or(p2), x); } public static void m1(Predicate<Integer> p, int[] x) { for (int x1 : x) { if (p.test(x1)) System.out.println(x1); } } }
Output
The Numbers Greater Than 10: 15 20 25 30 The Even Numbers Are: 0 10 20 30 The Numbers Not Greater Than 10: 0 5 10 The Numbers Greater Than 10 And Even Are: 20 30 The Numbers Greater Than 10 OR Even: 0 10 15 20 25 30
Differences between Predicate and Function
- Predicate is to implement conditional checks We should go for predicate where as Function is to perform certain operation And to return some result we Should go for function.
- Predicate can take one type Parameter which represents Input argument type. Predicate<T> where as Function can take 2 type Parameters. First one represent Input argument type and Second one represent return Type. Function<T,R>
- Predicate interface defines only one method called test() where as Function interface defines only one Method called apply().
- Predicate can return only boolean value where as Function can return any type of value.
Note: Predicate is a boolean valued function and(), or(), negate() are default methods present inside Predicate interface.
Supplier
Supplier takes no input and returns output.
import java.util.function.Supplier; public class SupplierDemo { public static void main(String args[]) { beforeJava8(); fromJava8(); } private static void beforeJava8() { double inrRate = getINRRate(); System.out.println("beforeJava8 :INR rate is " + inrRate); } public static double getINRRate() { double inrRate = 71.0; // call web service return inrRate; } private static void fromJava8() { double inrRate = 71.0;// Call webservice Supplier<Double> supplier = () -> inrRate; System.out.println("fromJava8 :INR rate is " + supplier.get()); } }
Output
beforeJava8 :INR rate is 71.0 fromJava8 :INR rate is 71.0
Consumer
Consumer takes single input and return nothing i.e. void.
import java.util.function.Consumer; public class ConsumerDemo { public static void main(String args[]) { beforeJava8(); fromJava8(); } private static void beforeJava8() { displayInLowerCase("Java 8"); } private static void displayInLowerCase(String str) { System.out.println(str.toLowerCase()); } private static void fromJava8() { Consumer<String> consumer = str -> System.out.println(str.toLowerCase()); consumer.accept("Java 8"); } }
Output
java 8 java 8
import java.util.function.Consumer; public class ConsumerDemo2 { public static void main(String args[]) { Consumer<String> consumer = message -> EmailUtility.sendEmail(message); consumer.accept("Your Account has been created"); } } class EmailUtility { public static void sendEmail(String message) { // to // Cc // Subject // Message BOdy // sendEmail(); System.out.println("Successfully sent an email with the message \n" + message); } }
Output
Successfully sent an email with the message Your Account has been created