Java Topic

Java Lambda Expressions

Lambda expressions, introduced in Java 8, provide a concise way to represent anonymous functions or methods. They enable you to pass behavior as a parameter, significantly simplifying the use of functional interfaces and making code more readable.

1. Syntax

The basic syntax of a lambda expression is:

(parameters) -> expression

Here's a breakdown:

  • Parameters: The input parameters of the lambda expression. If there is only one parameter, parentheses can be omitted.
  • Arrow Operator (->): Separates parameters and the body of the lambda expression.
  • Expression: The body of the lambda expression. If the body contains multiple statements, it must be enclosed in curly braces.

2. Examples

Single Parameter and Single Expression

import java.util.function.Function;

public class LambdaExample {
    public static void main(String[] args) {
        Function<Integer, Integer> square = x -> x * x;

        System.out.println("Square of 5: " + square.apply(5));
    }
}

This example demonstrates a lambda expression that takes an integer and returns its square.

Multiple Parameters and Multiple Statements

import java.util.function.BiFunction;

public class LambdaExample {
    public static void main(String[] args) {
        BiFunction<Integer, Integer, Integer> addAndMultiply = (a, b) -> {
            int sum = a + b;
            return sum * sum;
        };

        System.out.println("Result: " + addAndMultiply.apply(3, 4));
    }
}

This example shows a lambda expression with multiple parameters and statements. It adds two integers and returns the square of their sum.

3. Functional Interfaces

A lambda expression can be used wherever a functional interface is expected. A functional interface is an interface with a single abstract method (SAM). Some commonly used functional interfaces include:

  • Runnable
  • Callable
  • Function
  • Consumer
  • Supplier
  • Predicate

Using Lambda with a Functional Interface

import java.util.function.Consumer;

public class LambdaExample {
    public static void main(String[] args) {
        Consumer<String> print = s -> System.out.println(s);

        print.accept("Hello, Lambda!");
    }
}

This example demonstrates using a lambda expression with the Consumer functional interface to print a string.

4. Advantages

Lambda expressions offer several advantages:

  • Conciseness: They reduce boilerplate code by eliminating the need for anonymous classes.
  • Readability: They make the code more readable and expressive by focusing on the "what" rather than the "how."
  • Support for Functional Programming: They enable functional programming features like higher-order functions and lazy evaluation.

5. Common Use Cases

Lambda expressions are often used in:

  • Stream API: To specify operations on streams, such as filtering and mapping.
  • Event Handling: To handle events in GUI applications or frameworks.
  • Callback Functions: To pass behavior as parameters for asynchronous or parallel processing.

Lambda expressions are a powerful feature that enhance the flexibility and expressiveness of Java code, especially when combined with the Stream API and functional programming techniques.

Java Functional Interfaces

Functional interfaces are a key feature introduced in Java 8, which enable the use of lambda expressions and method references. A functional interface is an interface with exactly one abstract method, making it a target for lambda expressions and method references.

1. Definition

A functional interface is defined as an interface with a single abstract method. It can have multiple default or static methods, but it must have only one abstract method.

Example of a Functional Interface

@FunctionalInterface
public interface MyFunctionalInterface {
    void singleAbstractMethod();
}

The @FunctionalInterface annotation is optional but recommended, as it helps the compiler to enforce the functional interface contract.

2. Common Functional Interfaces

The Java standard library provides several common functional interfaces that are widely used:

  • Function: Represents a function that takes an argument of type T and returns a result of type R.
  • Consumer: Represents an operation that takes an argument of type T and returns no result.
  • Supplier: Represents a supplier of results of type T. It does not take any input but returns a result.
  • Predicate: Represents a predicate (boolean-valued function) of one argument of type T.
  • UnaryOperator: Represents an operation on a single operand of type T that produces a result of the same type.
  • BinaryOperator: Represents an operation on two operands of type T that produces a result of type T.

Examples

Function
import java.util.function.Function;

public class FunctionExample {
    public static void main(String[] args) {
        Function<Integer, String> intToString = x -> "Number: " + x;

        System.out.println(intToString.apply(10));
    }
}

This example demonstrates using a Function to convert an integer to a string.

Consumer
import java.util.function.Consumer;

public class ConsumerExample {
    public static void main(String[] args) {
        Consumer<String> print = s -> System.out.println(s);

        print.accept("Hello, World!");
    }
}

This example shows how to use a Consumer to print a string.

Supplier
import java.util.function.Supplier;

public class SupplierExample {
    public static void main(String[] args) {
        Supplier<Double> randomDouble = () -> Math.random();

        System.out.println("Random Double: " + randomDouble.get());
    }
}

This example demonstrates using a Supplier to generate a random double value.

Predicate
import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
        Predicate<Integer> isEven = x -> x % 2 == 0;

        System.out.println("Is 4 even? " + isEven.test(4));
    }
}

This example shows how to use a Predicate to test if a number is even.

3. Combining Functional Interfaces

Functional interfaces can be combined using default methods provided by the interface. For example:

  • Function: andThen() and compose() methods can be used to chain functions.
  • Predicate: and(), or(), and negate() methods can be used to combine predicates.

Combining Functions

import java.util.function.Function;

public class FunctionCombinationExample {
    public static void main(String[] args) {
        Function<Integer, Integer> multiplyBy2 = x -> x * 2;
        Function<Integer, Integer> add10 = x -> x + 10;

        Function<Integer, Integer> combinedFunction = multiplyBy2.andThen(add10);

        System.out.println("Result: " + combinedFunction.apply(5));
    }
}

This example demonstrates combining two functions using andThen() to first multiply a number and then add 10.

 

Comments (0)

No comments yet. Be the first to comment!

LecturreAI Assistant

Hello! I'm LecturreAI

What would you like to learn today?