Java Interview Questions (series) - Common Functional Interfaces
80% of the time you use 20% of the @FunctionalInterfaces π
Brief
π€ Β In a previous post, we spoke about the @FunctionalInterface
feature coming with Java 8.
We understood:
πΉ What is it used for?
πΉ What is it made of?
πΉ How you can create your own?
Java developers also created some out of the box functional interfaces to make our lives easier. π―
In this post, we'll go through the most used ones, what are they used for and how to use them on your particular use-case. π
Check out more posts like this on new-spike.net! π
Implementation
π΅ Β Predicate
Functional interface whose abstract method accepts a single element and returns a boolean
.
@FunctionalInterface
public interface Predicate<T> {
boolean test(T input);
}
Remembering from the previous post on functional interfaces, we need to provide an implementation for the test
abstract method.
πΈ Β Example
Let's create a predicate which determines if a given integer is even
or odd
.
Predicate<Integer> isEvenPredicate = input -> input%2 == 0; // provide implementation through a lambda expression
To use it, you only need to call its test
method.
boolean res1 = isEvenPredicate.test(4); // will return true
boolean res2 = isEvenPredicate.test(5); // will return false;
π΅ Β Consumer
Functional interface whose abstract method accepts a single element and returns void
.
@FunctionalInterface
public interface Consumer<T> {
void accept(T input);
}
πΈ Β Example
Let's say you want to print the element on the console.
Consumer<Integer> loggingConsumer = input -> System.out.println(input); // provide implementation through a lambda expression
And then, to apply it, you'll call the accept
method.
loggingConsumer.accept(2); // will print to the console: "2"
Check out more posts like this on new-spike.net! π
π΅ Β Supplier
Functional interface whose abstract method doesn't have any input parameters but returns a value.
@FunctionalInterface
public interface Supplier<T> {
T get();
}
πΈ Β Example
A use-case for this one might be to generate a random number.
Supplier<Double> randomSupplier = () -> Math.random(); // provide implementation through a lambda expression
To use it, you'll use the get
method.
Double random = randomSupplier.get();
π΅ Β Function
Functional interface whose abstract method accepts a single element as an input and also returns a value.
@FunctionalInterface
public interface Function<T, U> {
U apply(T input);
}
In other words, it's a combination of Consumer
and Supplier
.
This is the one you should use when you want to change the state of the elements, or generate a new type of object based on the input.
πΈ Β Example
You may have a User
object with a name
property.
Given a string provided as input for name, with Function
, you can create a User
with that particular name.
public class User {
private String name;
public User(String name) {
this.name = name;
}
}
User.java
Function<String, User> userFunction = input -> new User(input); // provide implementation through a lambda expression
User user = userFunction.apply("John Doe"); // generates a user with "John Doe" for name.
Check out more posts like this on new-spike.net! π
Bonus
Each of these functional interfaces that we just discussed, also have a correspondent which can accept 2 input parameters of different types.
Except the Supplier
one, of course, as it can't receive any parameter.
πΉ Β BiConsumer<T,U>
- accepts one T
parameter and one U
parameter and returns void
.
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u);
}
BiConsumer.java
BiConsumer<Integer, String> loggingConsumer = (input1, input2) -> System.out.println(input1 + input2);
loggingConsumer.accept(12, "apples"); // will print to the console: "12 apples"
Example
πΉ Β BiFunction<T,U,R>
- accepts one T
parameter and one U
parameter and returns a R
parameter.
@FunctionalInterface
public interface BiFunction<T, U, R> {
R apply(T t, U u);
}
BiFunction.java
public class User {
private String name;
private Integer age;
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
}
User.java
Function<String, Integer, User> userFunction = (name, age) -> new User(name, age); // provide implementation through a lambda expression
User user = userFunction.apply("John Doe", 23); // generates a user with "John Doe" for name and "23" for age.
Example
πΉ Β BiPredicate<T,U>
- accepts one T
parameter and one U
parameter and returns a boolean
.
@FunctionalInterface
public interface BiPredicate<T, U> {
boolean test(T t, U u);
}
BiPredicate<Integer, Integer> comparePredicate = (number1, number2) -> number1 >= number2;
comparePredicate.test(1,2); // returns false
comparePredicate.test(3,1); // returns true
Example
Check out more posts like this on new-spike.net! π