Course Content
Stream API
Stream API
Bi-versions of Functional Interfaces
In Java, there are several bi-versions of functional interfaces that work with two arguments. These interfaces provide convenient templates for performing various operations with a pair of input data, whether it's computing a result, performing an action, or checking a condition.
They simplify handling complex scenarios where you need to work with two parameters at once.
For example, instead of writing bulky code with multiple nested calls, you can take advantage of concise interfaces that provide ready-made methods for implementing key functionalities.
BiFunction<T, U, R>
BiFunction
is a functional interface that takes two input arguments of types T
and U
, and returns a result of type R
.
BiFunction
is ideal for tasks where two values need to be processed and a derived result is returned, such as computation, transformation, or data combination.
For example, if you need to calculate the total cost of items in stock by multiplying the quantity by the price per unit:
Main
package com.example; import java.util.function.BiFunction; public class Main { public static void main(String[] args) { // `BiFunction` to calculate total cost BiFunction<Integer, Double, Double> calculateTotalCost = (quantity, pricePerUnit) -> quantity * pricePerUnit; // Example usage int quantity = 50; double pricePerUnit = 19.99; double totalCost = calculateTotalCost.apply(quantity, pricePerUnit); System.out.println("Total cost: $" + totalCost); } }
In this example, BiFunction<Integer, Double, Double>
accepts two arguments: quantity
and pricePerUnit
(price per unit), and returns the result — the total cost as a Double
value. The apply()
method performs the specified operation, linking the functional interface with the multiplication logic.
BiConsumer<T, U>
BiConsumer
is a functional interface that takes two arguments of types T
and U
, but does not return a result.
It is used for performing actions on two objects, such as logging, displaying information, or saving data.
For example, let's create a functional interface that accepts an employee's name and salary, formats the data, and prints it to the console:
Main
package com.example; import java.util.HashMap; import java.util.Map; import java.util.function.BiConsumer; public class Main { public static void main(String[] args) { // `BiConsumer` for formatted output of employee details BiConsumer<String, Double> printEmployeeDetails = (name, salary) -> { System.out.printf("Employee: %-15s | Salary: $%.2f%n", name, salary); }; // Collection of employees with their salaries Map<String, Double> employeeData = new HashMap<>(); employeeData.put("John Smith", 75000.0); employeeData.put("Mary Johnson", 82000.0); employeeData.put("Robert Brown", 64000.0); employeeData.put("Emily Davis", 91000.0); // Print details of each employee System.out.println("Employee Salary Report:"); System.out.println("-----------------------------------"); employeeData.forEach(printEmployeeDetails); } }
In this example, BiConsumer<String, Double>
is used to process the employee's name and salary, printing the data to the console in a formatted way.
The forEach()
method of the Map
collection passes each key-value pair to the BiConsumer
, which performs the specified action for all employees.
BiPredicate<T, U>
BiPredicate
is a functional interface that takes two arguments of types T
and U
and returns a boolean result.
It is used for checking conditions where the result is a boolean value (true
or false
), based on the analysis of two input values.
For example, let's check whether the length of a string is greater than a given number:
Main
package com.example; import java.util.function.BiPredicate; public class Main { public static void main(String[] args) { // `BiPredicate` to check if string length is greater than given number BiPredicate<String, Integer> isStringLongerThan = (str, length) -> str.length() > length; // Example usage String text = "Sample string"; int minLength = 10; boolean result = isStringLongerThan.test(text, minLength); System.out.println("String is longer than " + minLength + " characters: " + result); } }
In this example, BiPredicate<String, Integer>
accepts two arguments: the string str
and the number length
, representing the minimum length. The test()
method checks the condition, returning true
if the string's length is greater than the specified number, or false
otherwise.
1. Which method is the main one in the BiFunction<T, U, R>
interface?
2. What does the accept(T t, U u)
method of the BiConsumer<T, U>
interface return?
3. Which interface is used to check a logical condition with two arguments?
Thanks for your feedback!