Java Tutorials
  • Introduction to Java
    • What is Java?
    • History and Features of Java
    • Java Virtual Machine (JVM) and Bytecode
    • Why Java?
  • Setting up Java Development Environment
    • Installing Java Development Kit (JDK)
    • JDK vs JRE
    • Setting up IDE (Eclipse, IntelliJ, NetBeans) or Text Editor (VS Code, Sublime Text)
  • Basic Java
    • First Java Program : Hello World
    • Variable
    • Data Type
    • Constant
    • Date and Format
    • Operator
    • Condition
    • Looping
    • Function
    • Variadic Function
    • Enums
    • Array
    • Collection
    • Exception and Exception Handling
    • Naming Convention
  • Object Oriented Programming (OOP)
    • Classes and Objects
    • Inheritance and Polymorphism
    • Encapsulation and Abstraction
  • File Handling
    • Reading and Writing Binary File
    • Reading and Writing Text File
    • Serialization and Deserialization
  • Multithreading
    • Creating and Running Threads
    • Synchronization
    • Thread Pools and Executors
  • Collections API
    • Sorting and Comparable
    • Searching and Comparator
  • Java Database Connectivity (JDBC)
    • Introduction and Life Cycle
    • Connection to Database (MySQL)
    • Downloading JDBC Drivers for Various Databases
    • Maven and Gradle JDBC Drivers for Various Databases
    • JDBC URL Formats
    • Statement and PreparedStatement
    • CallableStatement
    • Selecting Data using JDBC
    • Inserting Data using JDBC
    • Updating Data using JDBC
    • Deleting Data using JDBC
    • Invoking Function and Stored Procedure using JDBC
  • Lambda
    • Introduction to Lambda Expressions
    • Functional Interface
    • Filtering, Mapping, Reducing
    • Lambda Expressions in Collections
    • Method References
    • Functional Programming Concepts
    • Stream API
    • Error Handling in Lambda Expressions
    • Optional in Functional Programming
    • Parallel Processing with Lambda
    • Functional Programming Patterns
    • Advanced Topics in Lambda Expressions
    • Best Practices and Design Patterns
    • Real-World Use Cases and Examples
Powered by GitBook
On this page
  1. Lambda

Functional Programming Patterns

Functional Composition:

Functional Composition is a pattern where you combine two or more functions to produce a new function. It allows you to create complex behaviors by composing simpler functions.

Example of Functional Composition:

javaCopy codeimport java.util.function.Function;

public class FunctionalCompositionExample {
    public static void main(String[] args) {
        Function<Integer, Integer> addOne = x -> x + 1;
        Function<Integer, Integer> multiplyByTwo = x -> x * 2;

        // Function composition: (x -> (x + 1)) followed by (x -> (x * 2))
        Function<Integer, Integer> composedFunction = addOne.andThen(multiplyByTwo);

        int result = composedFunction.apply(3);
        System.out.println("Result: " + result); // Output: Result: 8
    }
}

In this example, addOne.andThen(multiplyByTwo) creates a composed function that first adds one to the input and then multiplies the result by two.

Currying:

Currying is a technique where a function takes multiple arguments and transforms it into a sequence of functions, each taking a single argument. It simplifies function composition and partial application.

Example of Currying:

javaCopy codeimport java.util.function.Function;

public class CurryingExample {
    public static void main(String[] args) {
        // Curried function: (x -> (y -> (x + y)))
        Function<Integer, Function<Integer, Integer>> curriedAddition = x -> y -> x + y;

        // Partial application: Apply 2 as the first argument
        Function<Integer, Integer> addTwo = curriedAddition.apply(2);

        int result = addTwo.apply(3);
        System.out.println("Result: " + result); // Output: Result: 5
    }
}

In this example, curriedAddition is a curried function. curriedAddition.apply(2) partially applies the function, creating a new function addTwo that adds 2 to its input.

Memoization:

Memoization is an optimization technique where the results of expensive function calls are cached, so that if the same inputs occur again, the cached result is returned instead of recalculating the result.

Example of Memoization:

javaCopy codeimport java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

public class MemoizationExample {
    private static final Map<Integer, Integer> cache = new ConcurrentHashMap<>();

    public static void main(String[] args) {
        // Memoized function for calculating factorial
        Function<Integer, Integer> factorial = n -> cache.computeIfAbsent(n,
                k -> (k == 0 || k == 1) ? 1 : k * factorial.apply(k - 1));

        int result = factorial.apply(5);
        System.out.println("Factorial of 5: " + result); // Output: Factorial of 5: 120
    }
}

In this example, factorial is a memoized function. The computeIfAbsent method of ConcurrentHashMap is used to cache the results. When factorial.apply(n) is called, it calculates the factorial of n and caches the result, preventing redundant calculations for the same input.

These functional programming patterns provide powerful tools for creating expressive, composable, and efficient code in Java. Functional composition, currying, and memoization enhance code readability, maintainability, and performance by encouraging the use of pure functions and immutable data.

PreviousParallel Processing with LambdaNextAdvanced Topics in Lambda Expressions

Last updated 1 year ago