📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.
✅ Some premium posts are free to read — no account needed. Follow me on Medium to stay updated and support my writing.
🎓 Top 10 Udemy Courses (Huge Discount): Explore My Udemy Courses — Learn through real-time, project-based development.
▶️ Subscribe to My YouTube Channel (172K+ subscribers): Java Guides on YouTube
Key points about the functional interface:
- An Interface that contains exactly one abstract method is known as a functional interface.
- It can have any number of default, static methods but can contain only one abstract method. It can also declare the methods of the object class.
- Functional Interface is also known as Single Abstract Method Interfaces or SAM Interfaces. It is a new feature in Java 8, which helps to achieve a functional programming approach.
- A functional interface can extend another interface only when it does not have any abstract method.
- The Java API has many one-method interfaces such as Runnable, Callable, Comparator, ActionListener, and others. They can be implemented and instantiated using anonymous class syntax.
Examples of Custom Functional Interface
Custom Functional Interface Example
@FunctionalInterface
interface Sayable{
void say(String msg); // abstract method
}
public class FunctionalInterfacesExample {
public static void main(String[] args) {
Sayable sayable = (msg) -> {
System.out.println(msg);
};
sayable.say("Say something ..");
}
}
Java 8 Predefined-Functional Interfaces
public class Person {
private String name;
private int age;
public Person(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;
}
}
Predicate Functional Interface
We need a function for checking a condition. A Predicate is one such function accepting a single argument to evaluate a boolean result.It has a single method test that returns the boolean value.
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
public class PredicateExample {
public static void main(String[] args) {
Predicate < Person > predicate = (person) -> person.getAge() > 28;
boolean result = predicate.test(new Person("ramesh", 29));
System.out.println(result);
}
}
Function Functional Interface
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
import java.util.function.Function;
public class FunctionExample {
public static void main(String[] args) {
// convert centigrade to fahrenheit
Function < Integer, Double > centigradeToFahrenheitInt = x -> new Double((x * 9 / 5) + 32);
// String to an integer
Function < String, Integer > stringToInt = x -> Integer.valueOf(x);
System.out.println(" String to Int: " + stringToInt.apply("4"));
Function < PersonEntity, PersonDTO > function = (entity) -> {
return new PersonDTO(entity.getName(), entity.getAge());
};
PersonDTO personDTO = function.apply(new PersonEntity("ramesh", 20));
System.out.println(personDTO.getName());
System.out.println(personDTO.getAge());
}
}
class PersonEntity {
private String name;
private int age;
public PersonEntity(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;
}
}
class PersonDTO {
private String name;
private int age;
public PersonDTO(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;
}
}
Supplier Functional Interface
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
import java.util.function.Supplier;
public class SuppliersExample {
public static void main(String[] args) {
Supplier<Person> supplier = () -> {
return new Person("Ramesh", 30 );
};
Person p = supplier.get();
System.out.println("Person Detail:\n" + p.getName() + ", " + p.getAge());
}
}
Consumer Functional Interface
@FunctionalInterface
public interface Consumer<T> {
void accept(T arg0);
default Consumer<T> andThen(Consumer<? super T> arg0) {
Objects.requireNonNull(arg0);
return (arg1) -> {
this.accept(arg1);
arg0.accept(arg1);
};
}
}
public class ConsumersExample {
public static void main(String[] args) {
List<Person> listOfPerson = new ArrayList<Person>();
listOfPerson.add(new Person("abc", 27));
listOfPerson.add(new Person("mno", 26));
listOfPerson.add(new Person("pqr", 28));
listOfPerson.add(new Person("xyz", 27));
listOfPerson.forEach((person) -> {
System.out.println(" Person name : " + person.getName());
System.out.println(" Person age : " + person.getAge());
});
// Second example
Consumer<Person> consumer = (person) -> {
System.out.println(person.getName());
System.out.println(person.getAge());
};
consumer.accept(new Person("Ramesh", 30));
}
}
BiFunction Functional Interface
@FunctionalInterface
public interface BiFunction<T, U, R> {
R apply(T arg0, U arg1);
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> arg0) {
Objects.requireNonNull(arg0);
return (arg1, arg2) -> {
return arg0.apply(this.apply(arg1, arg2));
};
}
}
public class BiFunctionExample {
public static void main(String[] args) {
BiFunction<Person, Person, Integer> biFunction = (p1,p2) -> {
return p1.getAge() + p2.getAge();
};
int totalAge = biFunction.apply(new Person("Ramesh", 10),
new Person("ram", 10));
System.out.println(totalAge);
}
}
BiConsumer Functional Interface
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T arg0, U arg1);
default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> arg0) {
Objects.requireNonNull(arg0);
return (arg1, arg2) -> {
this.accept(arg1, arg2);
arg0.accept(arg1, arg2);
};
}
}
public class BiConsumersExample { public static void main(String[] args) { BiConsumer<Person, Person> biConsumer = (p1, p2) -> { System.out.println(" print first persion"); System.out.println(p1.getName()); System.out.println(" print second persion"); System.out.println(p2.getName()); }; biConsumer.accept(new Person("Ramesh", 10), new Person("ram", 10)); } }
BiPredicate Functional Interface
@FunctionalInterface
public interface BiPredicate<T, U> {
boolean test(T t, U u);
// Default methods are defined also
}
package com.javaguides.java.functionalinterfaces;
import java.util.function.BiPredicate;
public class BiPredicateDemo {
public static void main(String[] args) {
// anonymous class implements BiPredicate interface
BiPredicate < String, String > predicateObject = new BiPredicate < String, String > () {
@Override
public boolean test(String s1, String s2) {
return s1.equals(s2);
}
};
System.out.println(predicateObject.test("Ramesh", "Ramesh"));
// Lambda expression implementation
BiPredicate < String, String > biPredicate = (s1, s2) -> s1.equals(s2);
System.out.println(biPredicate.test("ramesh", "ramesh"));
System.out.println(biPredicate.test("java guides", "Java Guides"));
}
}
true
true
false
Summary
- A functional interface is an interface that has exactly one abstract method.
- Since default methods have an implementation, they are not abstract so a functional interface can have any number of them.
- If an interface declares an abstract method with the signature of one of the methods of java.lang.Object, it doesn't count toward the functional interface method count.
- A functional interface is valid when it inherits a method that is equivalent but not identical to another.
- An empty interface is not considered a functional interface.
- A functional interface is valid even if the @FunctionalInterface annotation would be omitted.
- Functional interfaces are the basis of lambda expressions.
Source Code on GitHub
The source code of this article is available on GitHub Repository.4. Related Java 8 Top Posts
- Java 8 Lambda Expressions
- Java 8 Functional Interfaces
- Java 8 Method References
- Java 8 Stream API
- Java 8 Optional Class
- Java 8 Collectors Class
- Java 8 StringJoiner Class
- Java 8 Static and Default Methods in Interface
- Guide to Java 8 forEach Method
- Handle NullPointerException using Java 8 Optional Class
- How to Use Java 8 Stream API in Java Projects
- Migrating Source Code to Java 8
Comments
Post a Comment
Leave Comment