[Java] Jdk8 function interface Supplier, Function, Predicate, Consumer, BiFunction, BiPredicate, BiConsumer

Overview

Supplier, Function, Predicate, Consumer, BiFunction, BiPredicate, BiConsumer are part of the Java functional interface, which are used to define different types of functions, thus providing a more flexible way to process data in functional programming.

  • Supplier: Represents a supplier that does not accept any parameters, but returns a result. Its abstract method is T get(), which is used to obtain a result.

  • Function: Represents a function that takes one parameter and returns one result. Its abstract method is R apply(T t), which is used to convert input parameters into output results.

  • Predicate: Represents an assertion that takes one parameter and returns a boolean value. Its abstract method is boolean test(T t), which is used to conditionally judge the input parameters.

  • Consumer: Represents a consumer that accepts a parameter and returns no value. Its abstract method is void accept(T t), which is used to perform some operations on input parameters.

  • BiFunction: Represents a function that accepts two parameters and returns a result. Its abstract method is R apply(T t, U u), which is used to convert two input parameters into an output result.

  • BiPredicate: Represents a predicate that accepts two parameters and returns a Boolean value. Its abstract method is boolean test(T t, U u), which is used for conditional judgment on two input parameters.

  • BiConsumer: Represents an operation that accepts two parameters and returns no value. Its abstract method is void accept(T t, U u), which is used to perform some operations on two input parameters.

These functional interfaces can be implemented through Lambda expressions, which simplifies the writing of code. In functional programming, they can be used as method parameters or return values to describe different behaviors and operations, improving the readability and maintainability of the code.

Detailed

Supplier

  • Abstract method: T get()
  • Purpose: Indicates a supplier, does not accept any parameters, and returns a result.
  • Usage scenario: When you need to obtain an object, and the creation logic of the object is complex or needs to be reused, Supplier can be used.
public class ProductManager {
    public static void main(String[] args) {
        Product product = createProduct(() -> {
            // Obtain product information from the database and create a Product object
            return getFromDatabase();
        });

        System.out.println(product);
    }

    public static Product createProduct(Supplier<Product> supplier) {
        return supplier. get();
    }

    public static Product getFromDatabase() {
        // Get product information from the database
        //...
        return new Product("iPhone", 999);
    }
}
class Product {
    private String name;
    private double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + ''' +
                ", price=" + price +
                '}';
    }
}

Function

  • Abstract method: R apply(T t)
  • Purpose: Represents a function that accepts one input parameter and returns one result.
  • Usage scenario: Function can be used when input parameters need to be processed and a result returned.
public class SalaryCalculator {
    public static void main(String[] args) {
        Employee employee = new Employee("John", 40, 25.0);
        double salary = calculateSalary(employee, emp -> emp. getHoursWorked() * emp. getHourlyRate());
        System.out.println("Salary: " + salary);
    }

    public static double calculateSalary(Employee employee, Function<Employee, Double> salaryFunction) {
        return salaryFunction. apply(employee);
    }
}

class Employee {
    private String name;
    private int hoursWorked;
    private double hourlyRate;

    public Employee(String name, int hoursWorked, double hourlyRate) {
        this.name = name;
        this.hoursWorked = hoursWorked;
        this. hourlyRate = hourlyRate;
    }

    public String getName() {
        return name;
    }

    public int getHoursWorked() {
        return hoursWorked;
    }

    public double getHourlyRate() {
        return hourlyRate;
    }
}

Predicate

  • Abstract method: boolean test(T t)
  • Purpose: Represents an assertion that accepts an input parameter and returns a Boolean value.
  • Usage scenario: Predicate can be used when conditional judgment on input parameters is required.
public class FilterFruits {
    public static void main(String[] args) {
        List<Fruit> fruits = new ArrayList<>();
        fruits.add(new Fruit("Apple", "Red", 100));
        fruits.add(new Fruit("Banana", "Yellow", 150));
        fruits.add(new Fruit("Orange", "Orange", 120));

        List<Fruit> redFruits = filterFruits(fruits, fruit -> fruit. getColor(). equals("Red"));
        System.out.println("Red fruits: " + redFruits);
    }

    public static List<Fruit> filterFruits(List<Fruit> fruits, Predicate<Fruit> predicate) {
        List<Fruit> filteredFruits = new ArrayList<>();
        for (Fruit fruit : fruits) {
            if (predicate. test(fruit)) {
                filteredFruits. add(fruit);
            }
        }
        return filteredFruits;
    }
}

class Fruit {
    private String name;
    private String color;
    private int weight;

    public Fruit(String name, String color, int weight) {
        this.name = name;
        this.color = color;
        this.weight = weight;
    }

    public String getName() {
        return name;
    }

    public String getColor() {
        return color;
    }

    public int getWeight() {
        return weight;
    }

    @Override
    public String toString() {
        return "Fruit{" +
                "name='" + name + ''' +
                ", color='" + color + ''' +
                ", weight=" + weight +
                '}';
    }
}

Consumer

  • Abstract method: void accept(T t)
  • Purpose: Indicates an operation that accepts an input parameter and returns no value.
  • Usage scenario: When you need to perform some operations on input parameters without returning results, you can use Consumer.
public class ProcessNumbers {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers. add(1);
        numbers. add(2);
        numbers. add(3);
        numbers. add(4);
        numbers. add(5);

        processNumbers(numbers, number -> System. out. println("Processing number: " + number));
    }

    public static void processNumbers(List<Integer> numbers, Consumer<Integer> consumer) {
        for (Integer number : numbers) {
            consumer. accept(number);
        }
    }
}

BiFunction, BiPredicate, BiConsumer

Same as Function, Predicate, Consumer, only one input parameter becomes two

Bi is used in many places in the Mybatis framework, such as: ResultHandler, ResultSetHandler, ParameterHandler, StatementHandler