Java Functional Interface: Difference between revisions
Created page with "=Functional Interface= A functional interface is an interface that contains only one abstract method. They can have only one functionality to exhibit. =Java Example= Before Java 8, we had to create anonymous inner class objects or implement these interfaces. <syntaxhighlight lang="java"> // Java program to demonstrate functional interface class Test { public static void main(String args[]) { // create anonymous inner class object new Thread(ne..." |
No edit summary |
||
(One intermediate revision by the same user not shown) | |||
Line 1: | Line 1: | ||
=Functional Interface= | = Java Functional Interface = | ||
A | |||
=Java Example= | A **Functional Interface** in Java is an interface that contains exactly one abstract method. It can have multiple default or static methods, but only one abstract method is allowed. Functional interfaces are the foundation of **lambda expressions** and **method references** introduced in **Java 8**. | ||
Before Java 8 | |||
<syntaxhighlight lang="java"> | == Key Characteristics == | ||
* Contains exactly '''one abstract method'''. | |||
* Can have '''default''' and '''static methods'''. | |||
class | * Annotated with <code>@FunctionalInterface</code> (optional but recommended for clarity). | ||
{ | * Enables functional programming in Java. | ||
public static void main(String | |||
== Examples of Built-in Functional Interfaces == | |||
// | Java provides several built-in functional interfaces in the <code>java.util.function</code> package: | ||
{| class="wikitable" | |||
! Functional Interface !! Abstract Method !! Description !! Example | |||
|- | |||
| <code>Function<T, R></code> || <code>R apply(T t)</code> || Takes one argument and produces a result. || <code>String::length</code> | |||
|- | |||
| <code>Consumer<T></code> || <code>void accept(T t)</code> || Takes one argument and performs an operation without returning a result. || <code>System.out::println</code> | |||
|- | |||
| <code>Supplier<T></code> || <code>T get()</code> || Produces a result without taking any arguments. || <code>() -> "Hello"</code> | |||
|- | |||
| <code>Predicate<T></code> || <code>boolean test(T t)</code> || Evaluates a condition and returns a boolean. || <code>x -> x > 10</code> | |||
|- | |||
| <code>BiFunction<T, U, R></code> || <code>R apply(T t, U u)</code> || Takes two arguments and produces a result. || <code>(x, y) -> x + y</code> | |||
|} | |||
== Before and After Functional Interfaces == | |||
=== Before Java 8 (Using Anonymous Classes) === | |||
<syntaxhighlight lang="java"> | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
public class BeforeFunctionalInterface { | |||
public static void main(String[] args) { | |||
List<String> names = List.of("Alice", "Bob", "Charlie"); | |||
// Using an anonymous class to filter names | |||
List<String> filteredNames = filterNames(names, new Predicate<String>() { | |||
@Override | @Override | ||
public | public boolean test(String name) { | ||
return name.startsWith("A"); | |||
} | } | ||
}). | }); | ||
System.out.println(filteredNames); // Output: [Alice] | |||
} | |||
public static List<String> filterNames(List<String> names, Predicate<String> predicate) { | |||
List<String> result = new ArrayList<>(); | |||
for (String name : names) { | |||
if (predicate.test(name)) { | |||
result.add(name); | |||
} | |||
} | |||
return result; | |||
} | |||
} | |||
</syntaxhighlight> | |||
=== After Java 8 (Using Lambda Expressions) === | |||
<syntaxhighlight lang="java"> | |||
import java.util.List; | |||
import java.util.function.Predicate; | |||
import java.util.stream.Collectors; | |||
public class AfterFunctionalInterface { | |||
public static void main(String[] args) { | |||
List<String> names = List.of("Alice", "Bob", "Charlie"); | |||
// Using a lambda expression to filter names | |||
List<String> filteredNames = names.stream() | |||
.filter(name -> name.startsWith("A")) | |||
.collect(Collectors.toList()); | |||
System.out.println(filteredNames); // Output: [Alice] | |||
} | |||
} | |||
</syntaxhighlight> | |||
== Custom Functional Interface == | |||
You can create your own functional interface by defining an interface with a single abstract method. | |||
<syntaxhighlight lang="java"> | |||
@FunctionalInterface | |||
public interface StringProcessor { | |||
String process(String input); | |||
} | |||
</syntaxhighlight> | |||
=== Example Usage === | |||
<syntaxhighlight lang="java"> | |||
public class CustomFunctionalInterfaceExample { | |||
public static void main(String[] args) { | |||
// Using a lambda expression | |||
StringProcessor toUpperCase = input -> input.toUpperCase(); | |||
System.out.println(toUpperCase.process("hello")); // Output: HELLO | |||
// Using a method reference | |||
StringProcessor trim = String::trim; | |||
System.out.println(trim.process(" hello ")); // Output: hello | |||
} | |||
} | |||
</syntaxhighlight> | |||
== Advanced Features == | |||
=== Chaining Functional Interfaces === | |||
You can chain functional interfaces using methods like <code>andThen</code> and <code>compose</code>. | |||
<syntaxhighlight lang="java"> | |||
import java.util.function.Function; | |||
public class FunctionChainingExample { | |||
public static void main(String[] args) { | |||
Function<String, Integer> stringLength = String::length; | |||
Function<Integer, Integer> square = x -> x * x; | |||
// Chain functions | |||
Function<String, Integer> lengthThenSquare = stringLength.andThen(square); | |||
System.out.println(lengthThenSquare.apply("Hello")); // Output: 25 | |||
} | |||
} | |||
</syntaxhighlight> | |||
=== Combining Predicates === | |||
You can combine <code>Predicate</code> instances using <code>and</code>, <code>or</code>, and <code>negate</code>. | |||
<syntaxhighlight lang="java"> | |||
import java.util.function.Predicate; | |||
public class PredicateExample { | |||
public static void main(String[] args) { | |||
Predicate<String> startsWithA = s -> s.startsWith("A"); | |||
Predicate<String> endsWithZ = s -> s.endsWith("Z"); | |||
Predicate<String> combined = startsWithA.and(endsWithZ); | |||
System.out.println(combined.test("Alice")); // Output: false | |||
System.out.println(combined.test("AtoZ")); // Output: true | |||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Benefits of Functional Interfaces == | |||
* **Conciseness**: Reduces boilerplate code by replacing anonymous classes with lambda expressions. | |||
* **Reusability**: Enables passing behavior as parameters, making code more modular. | |||
* **Stream API Integration**: Works seamlessly with the Stream API for declarative programming. | |||
* **Improved Readability**: Simplifies code, making it easier to understand. | |||
== Summary == | |||
Functional interfaces are a cornerstone of functional programming in Java. They enable concise, reusable, and readable code by allowing behavior to be passed as parameters. By leveraging built-in functional interfaces and creating custom ones, you can write modern, maintainable Java applications. |
Latest revision as of 00:39, 4 July 2025
Java Functional Interface
A **Functional Interface** in Java is an interface that contains exactly one abstract method. It can have multiple default or static methods, but only one abstract method is allowed. Functional interfaces are the foundation of **lambda expressions** and **method references** introduced in **Java 8**.
Key Characteristics
- Contains exactly one abstract method.
- Can have default and static methods.
- Annotated with
@FunctionalInterface
(optional but recommended for clarity). - Enables functional programming in Java.
Examples of Built-in Functional Interfaces
Java provides several built-in functional interfaces in the java.util.function
package:
Functional Interface | Abstract Method | Description | Example |
---|---|---|---|
Function<T, R> |
R apply(T t) |
Takes one argument and produces a result. | String::length
|
Consumer<T> |
void accept(T t) |
Takes one argument and performs an operation without returning a result. | System.out::println
|
Supplier<T> |
T get() |
Produces a result without taking any arguments. | () -> "Hello"
|
Predicate<T> |
boolean test(T t) |
Evaluates a condition and returns a boolean. | x -> x > 10
|
BiFunction<T, U, R> |
R apply(T t, U u) |
Takes two arguments and produces a result. | (x, y) -> x + y
|
Before and After Functional Interfaces
Before Java 8 (Using Anonymous Classes)
import java.util.ArrayList;
import java.util.List;
public class BeforeFunctionalInterface {
public static void main(String[] args) {
List<String> names = List.of("Alice", "Bob", "Charlie");
// Using an anonymous class to filter names
List<String> filteredNames = filterNames(names, new Predicate<String>() {
@Override
public boolean test(String name) {
return name.startsWith("A");
}
});
System.out.println(filteredNames); // Output: [Alice]
}
public static List<String> filterNames(List<String> names, Predicate<String> predicate) {
List<String> result = new ArrayList<>();
for (String name : names) {
if (predicate.test(name)) {
result.add(name);
}
}
return result;
}
}
After Java 8 (Using Lambda Expressions)
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class AfterFunctionalInterface {
public static void main(String[] args) {
List<String> names = List.of("Alice", "Bob", "Charlie");
// Using a lambda expression to filter names
List<String> filteredNames = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());
System.out.println(filteredNames); // Output: [Alice]
}
}
Custom Functional Interface
You can create your own functional interface by defining an interface with a single abstract method.
@FunctionalInterface
public interface StringProcessor {
String process(String input);
}
Example Usage
public class CustomFunctionalInterfaceExample {
public static void main(String[] args) {
// Using a lambda expression
StringProcessor toUpperCase = input -> input.toUpperCase();
System.out.println(toUpperCase.process("hello")); // Output: HELLO
// Using a method reference
StringProcessor trim = String::trim;
System.out.println(trim.process(" hello ")); // Output: hello
}
}
Advanced Features
Chaining Functional Interfaces
You can chain functional interfaces using methods like andThen
and compose
.
import java.util.function.Function;
public class FunctionChainingExample {
public static void main(String[] args) {
Function<String, Integer> stringLength = String::length;
Function<Integer, Integer> square = x -> x * x;
// Chain functions
Function<String, Integer> lengthThenSquare = stringLength.andThen(square);
System.out.println(lengthThenSquare.apply("Hello")); // Output: 25
}
}
Combining Predicates
You can combine Predicate
instances using and
, or
, and negate
.
import java.util.function.Predicate;
public class PredicateExample {
public static void main(String[] args) {
Predicate<String> startsWithA = s -> s.startsWith("A");
Predicate<String> endsWithZ = s -> s.endsWith("Z");
Predicate<String> combined = startsWithA.and(endsWithZ);
System.out.println(combined.test("Alice")); // Output: false
System.out.println(combined.test("AtoZ")); // Output: true
}
}
Benefits of Functional Interfaces
- **Conciseness**: Reduces boilerplate code by replacing anonymous classes with lambda expressions.
- **Reusability**: Enables passing behavior as parameters, making code more modular.
- **Stream API Integration**: Works seamlessly with the Stream API for declarative programming.
- **Improved Readability**: Simplifies code, making it easier to understand.
Summary
Functional interfaces are a cornerstone of functional programming in Java. They enable concise, reusable, and readable code by allowing behavior to be passed as parameters. By leveraging built-in functional interfaces and creating custom ones, you can write modern, maintainable Java applications.