Java Functional Interface: Difference between revisions

From bibbleWiki
Jump to navigation Jump to search
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 functional interface is an interface that contains only one abstract method. They can have only one functionality to exhibit.
 
=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, we had to create anonymous inner class objects or implement these interfaces.
 
<syntaxhighlight lang="java">  
== Key Characteristics ==
// Java program to demonstrate functional interface
* Contains exactly '''one abstract method'''.
 
* Can have '''default''' and '''static methods'''.
class Test
* Annotated with <code>@FunctionalInterface</code> (optional but recommended for clarity).
{
* Enables functional programming in Java.
     public static void main(String args[])
 
    {
== Examples of Built-in Functional Interfaces ==
         // create anonymous inner class object
Java provides several built-in functional interfaces in the <code>java.util.function</code> package:
         new Thread(new Runnable()
 
        {
{| class="wikitable"
! Functional Interface !! Abstract Method !! Description !! Example
|-
| <code>Function&lt;T, R&gt;</code> || <code>R apply(T t)</code> || Takes one argument and produces a result. || <code>String::length</code>
|-
| <code>Consumer&lt;T&gt;</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&lt;T&gt;</code> || <code>T get()</code> || Produces a result without taking any arguments. || <code>() -> "Hello"</code>
|-
| <code>Predicate&lt;T&gt;</code> || <code>boolean test(T t)</code> || Evaluates a condition and returns a boolean. || <code>x -> x > 10</code>
|-
| <code>BiFunction&lt;T, U, R&gt;</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 void run()
             public boolean test(String name) {
            {
                 return name.startsWith("A");
                 System.out.println("New thread created");
             }
             }
         }).start();
         });
 
        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.