Single Abstract Methods
The Consumer<T>
, Function<T, R>
, and Predicate<T>
lambdas that we may have seen earlier fall under java.util.function
interface Predicate<T> {
boolean test(T t);
}
interface Consumer<T> {
void accept(T t);
Consumer<T> andThen(Consumer<? super T> after);
}
interface Supplier<T> {
T get();
}
class Foo {
Predicate<Integer> p = x->x > 3; // define a predicate
// print out all integers in range [0, 10) that are greater than 3.
for (int i = 0; i < 10; ++i) {
if (p(i)) {
System.out.println(i);
}
}
}
/* The above code is equivalent to the following */
import java.util.function.Predicate; // using java function library
class Foo {
Predicate<Integer> p = x->x > 3;
for (int i = 0; i < 10; ++i) {
if (p(i)) {
System.out.println(i);
}
}
}
import java.util.function.Predicate; // using java function library
class Foo {
Predicate<Integer> p = new Predicate<Integer> {
@Override
public boolean test(Integer t) {
return t > 3;
}
};
for (int i = 0; i < 10; ++i) {
if (p(i)) {
System.out.println(i);
}
}
}
Additionally we can annotate a class with @FunctionalInterface to hint our intentions to the compiler and let the compiler help us catch any unintended error.
We can define our own functional interface as well.
@FunctionalInterface
interface GetGrade{
A takeGrade();
}
GetGrade good = test -> test.takeGrade();
For more information on functional interfaces, check out java documentation here.