Function and BiFunction Functional Interface
In my previous
blog, I’ve already talked about Predicate and BiPredicate Functional Interface.
In this blog, I’ll talk about next predefined Functional Interface i.e. Function
and BiFunction Functional Interface.
Function is a
Functional Interface which accept single input and returns another. The functional
method of Predicate is R apply(T t).
@FunctionalInterface
Public interface Function<T,
R> { …}
Here is a simple source code of java.util.function.Function
package
java.util.function;
import
java.util.Objects;
@FunctionalInterface
public interface Function<T,
R> {
public <R> apply(T t);
}
Where R apply (T t) is an abstract method where T is the type of the input to the Function
and will return type of R.
Example 1:
import java.util.function.Function;
public class FunctionExample {
public static void main(String[] args) {
// Calling
Function Functional Interface without using Lambda Expression
FunctionExample.GetStringLength function = new FunctionExample().new GetStringLength();
System.out.println("Length of String is : " + function.apply("www.waheedtechblog.com"));
// Using
Lambda Expression
Function<String, Integer> f1 = (name) -> name.length();
System.out.println("Lambda Expression, Length of String is : " + f1.apply("www.waheedtechblog.com"));
}
class GetStringLength implements Function<String, Integer> {
@Override
public Integer apply(String name) {
return name.length();
}
}
}
Example 2:
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class FunctionExample2 {
public static void main(String[] args) {
FunctionExample2 functionExample2 = new FunctionExample2();
Function<Student, String> f2 = student -> student.getName();
List<Student> students = functionExample2.populateStudentList();
for (Student student : students) {
System.out.println("Student Name: " + f2.apply(student));
}
}
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;
}
}
}
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:
Student
Name: Abdul
Student
Name: Waheed
Student
Name: DummyUser
Student
Name: Adam
Apart from R Apply (T t) method, Function also has 2 default method and
one static method.
Modifier and Type
|
Method and Description
|
Returns a composed function that
first applies this function to its input, and then applies the after function
to the result.
|
|
Returns a composed function that
first applies the before function to its input, and then applies
this function to the result.
|
|
static <T> Function<T,T>
|
identity()
Returns a function that always
returns its input argument.
|
1.
andThen():
default method combines the current Function instance
with another one and returns a combined Function instance which applies the two
functions in sequence with the function passed as parameter to andThen()
being invoked after the current
function.
2.
compose():
default method combines the current Function instance
with another one and returns a combined Function instance which applies the two
functions in sequence with the parameter function to compose()
being invoked before the current
function.
3.
identity()
: it just returns
back the parameter which it gets as input.
Let’s understand it with few more example
Example 3:
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class FunctioalExample3 {
public static void main(String[] args) {
FunctioalExample3 functioalExample3 = new FunctioalExample3();
// return the
name of Student
Function<Student, String> f1 = student -> student.getName();
// return
name in uppercase
Function<String, String> f2 = name -> name.toUpperCase();
Function<Student, Student> f3 = student -> {
String name = "Adding
via Compose " + student.getName();
return new Student(name, student.getAge());
};
Function<String, String> f4 = Function.identity();
// andThen
default method
System.out.println("=============================");
System.out.println("=====USING andThen Default Function======");
List<Student> students = functioalExample3.populateStudentList();
for (Student student : students) {
System.out.println("Student Name: " + f1.andThen(f2).apply(student));
}
// compose
default method
System.out.println("\n");
System.out.println("=============================");
System.out.println("=====USING default COMPOSE FUNCTION======");
for (Student student : students) {
System.out.println("Student Name: " + f1.compose(f3).apply(student));
}
// Identity
Static method
System.out.println("\n");
System.out.println("=============================");
System.out.println("=====Identity Static method======");
for (Student student : students) {
System.out.println("Student Name: " + f4.apply(student.getName()));
}
}
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:
=============================
=====USING
andThen Default Function======
Student
Name: ABDUL
Student
Name: WAHEED
Student
Name: DUMMYUSER
Student
Name: ADAM
=============================
=====USING
default COMPOSE FUNCTION======
Student
Name: Adding via Compose Abdul
Student
Name: Adding via Compose Waheed
Student
Name: Adding via Compose DummyUser
Student
Name: Adding via Compose Adam
=============================
=====Identity
Static method======
Student
Name: Abdul
Student
Name: Waheed
Student
Name: DummyUser
Student
Name: Adam
BiFunction
It is very similar to Function Functional
Interface. The only difference is just that it will accept two input arguments instead
of one and as usual will return another.
@FunctionalInterface
public interface BiFunction<T,U,R>
{
R
apply(T t, U u);
}
Let’s see another example
Example 4:
import java.util.function.BiFunction;
public class BiFunctionExample {
public static void main(String[] args) {
BiFunction<Integer, Integer,
Integer> area = (a, b) -> a * b;
System.out.println("Area of Rectangle: " + area.apply(5, 10));
}
}
Output:
Area of
Rectangle: 50
That’s it for Function and BiFunction
Functional Interface, Will talk about other Predefined Functional Interface in
my next blog.
Happy Coding…!!!