Java CompletableFuture thenCombine() Method

The CompletableFuture class in Java provides the thenCombine() method to combine the results of two CompletableFuture instances when both complete.

Introduction

The CompletableFuture.thenCombine() method is used to combine the results of two CompletableFuture instances once both complete. It takes a BiFunction that processes the results of both futures and returns a new CompletableFuture with the combined result.

thenCombine Method Syntax

The syntax for the thenCombine method is as follows:

public <U, V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other, BiFunction<? super T, ? super U, ? extends V> fn)
  • The method takes two parameters:
    • other of type CompletionStage<? extends U>, which is the other CompletableFuture to combine with.
    • fn of type BiFunction<? super T, ? super U, ? extends V>, which represents the function to combine the results of both futures.
  • The method returns a new CompletableFuture<V> that holds the combined result.

Examples

Example 1: Combining Results of Two Asynchronous Tasks

In a scenario where you have two CompletableFuture instances that complete with different results, you might want to combine their results into a single future.

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.BiFunction;

public class ThenCombineExample {
    public static void main(String[] args) {
        // Create two CompletableFuture instances
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");

        // Combine the results of both futures using thenCombine
        CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + " " + result2);

        // Process the combined result
        combinedFuture.thenAccept(result -> System.out.println("Combined result: " + result));

        // Wait for the combined future to complete
        try {
            combinedFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

Output:

Combined result: Hello World

Example 2: Task Management System

In a task management system, you might want to combine the results of two tasks to create a summary report.

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.BiFunction;

public class TaskManagementSystem {
    public static void main(String[] args) {
        // Create two CompletableFuture instances for tasks
        CompletableFuture<Task> taskFuture1 = CompletableFuture.supplyAsync(() -> new Task("Complete project report", 2));
        CompletableFuture<Task> taskFuture2 = CompletableFuture.supplyAsync(() -> new Task("Email client updates", 1));

        // Combine the results of both tasks into a summary report
        CompletableFuture<String> summaryFuture = taskFuture1.thenCombine(taskFuture2, (task1, task2) ->
            "Summary:\n" + task1 + "\n" + task2
        );

        // Process the summary report
        summaryFuture.thenAccept(summary -> System.out.println(summary));

        // Wait for the summary future to complete
        try {
            summaryFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

class Task {
    private String description;
    private int priority;

    public Task(String description, int priority) {
        this.description = description;
        this.priority = priority;
    }

    @Override
    public String toString() {
        return description + " (Priority: " + priority + ")";
    }
}

Output:

Summary:
Complete project report (Priority: 2)
Email client updates (Priority: 1)

Example 3: Combining Financial Data

In a financial application, you might want to combine the results of two asynchronous data fetches to calculate the total balance.

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.BiFunction;

public class FinancialDataExample {
    public static void main(String[] args) {
        // Create two CompletableFuture instances for fetching account balances
        CompletableFuture<Double> savingsBalanceFuture = CompletableFuture.supplyAsync(() -> 1500.00);
        CompletableFuture<Double> checkingBalanceFuture = CompletableFuture.supplyAsync(() -> 2500.00);

        // Combine the results of both balances to calculate the total balance
        CompletableFuture<Double> totalBalanceFuture = savingsBalanceFuture.thenCombine(checkingBalanceFuture, Double::sum);

        // Process the total balance
        totalBalanceFuture.thenAccept(totalBalance -> System.out.println("Total balance: $" + totalBalance));

        // Wait for the total balance future to complete
        try {
            totalBalanceFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

Output:

Total balance: $4000.0

Conclusion

The CompletableFuture.thenCombine() method in Java is used for combining the results of two CompletableFuture instances once both complete. It is particularly useful in scenarios where you need to process and combine the results of multiple asynchronous computations, such as combining results of different tasks, creating summary reports, or aggregating financial data.

Comments