簡體   English   中英

根據條件鏈接可完成的期貨

[英]Chaining completable futures based on conditions

我有一堆返回CompletableFuture的方法,我想以一種特定的方式鏈接

package com.sandbox;

import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.stream.IntStream;

public class SandboxFutures {

    public CompletableFuture<Integer> generateRandom(int min, int max) {
        return CompletableFuture.supplyAsync(() -> {
            if (min >= max) {
                throw new IllegalArgumentException("max must be greater than min");
            }

            Random r = new Random();
            return r.nextInt((max - min) + 1) + min;
        });
    }

    public CompletableFuture<String> printEvenOrOdd(int result) {
        return CompletableFuture.supplyAsync(() -> {
            if (result % 2 == 0)
                return "Even";
            else
                return "Odd";
        });
    }

    public CompletableFuture<Integer> findFactorial(int evenNumber) {
        return CompletableFuture.supplyAsync(() -> {
            if (evenNumber <= 0) {
                return 0;
            }

            return IntStream.rangeClosed(2, evenNumber).reduce(1, (x,y) -> x*y);
        });
    }

    public CompletableFuture<Integer> convertToNearestEvenInteger(int oddNumber) {
        return CompletableFuture.supplyAsync(() -> {
           if (oddNumber <= 0) {
               return 2;
           }
           return oddNumber+1;
        });
    }

}

我正在嘗試根據以下規則將它們合並,

  1. 產生1到100之間的隨機數
  2. 如果數字是偶數打印Even ,如果是奇數則打印Odd
  3. 如果該數字是偶數, findFactorial使用隨機數調用findFactorial
  4. 如果數字是奇數,則通過convertToNearestEvenInteger查找最接近的偶數

我不太清楚如何進行條件鏈接和異常處理。 一些示例或代碼片段可能會有所幫助。

您可以使用thenCompose()

CompletableFuture<Integer> n = generateRandom(1, 100)
        .thenCompose(i -> printEvenOrOdd(i)
                .thenCompose(s -> s.equals("Even")
                        ? findFactorial(i)
                        : convertToNearestEvenInteger(i)));
System.out.println(n.get());

但是,當生成大偶數時,階乘方法不能存儲大於int任何值,因此您需要對其進行更新。

printEvenOrOdd的寫入方式使其變得比所需的難度更大。 問題是它不打印單詞“ Even”或“ Odd”,而是返回它,這意味着原始result丟失了。 其余步驟依賴於實際數字。 要解決此問題,可以使用調用printEvenOrOdd並使用.thenApply(__ -> result)再恢復原始數字。 它看起來像這樣:

System.out.println(
    generateRandom(1, 100)
        .thenCompose(result ->
            printEvenOrOdd(result)
                .thenAccept(System.out::println)
                .thenApply(__ -> result)
        )
        .thenCompose(result ->
            result % 2 == 0
                ? findFactorial(result)
                : convertToNearestEvenInteger(result)
        )
        .join()
);

更好的解決方案是將printEvenOrOdd的定義更改為:

public CompletableFuture<Integer> printEvenOrOdd(int result) {
    return CompletableFuture.supplyAsync(() -> {
        System.out.println(result % 2 == 0 ? "Even" : "Odd");
        return result;
    });
}

這將使鏈接步驟3和4變得更加容易:

System.out.println(
    generateRandom(1, 100)
        .thenApply(this::printEvenOrOdd)
        .thenCompose(result ->
            result % 2 == 0
                ? findFactorial(result)
                : convertToNearestEvenInteger(result)
        )
        .join()
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM