2

我有一堆返回 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用随机数调用
  4. 如果数字是奇数,则通过查找最近的偶数convertToNearestEvenInteger

我不太清楚如何进行条件链接和异常处理。一些示例或代码片段可能会有所帮助。

4

2 回答 2

2

您可以使用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,因此您需要对其进行更新。

于 2019-03-08T04:34:31.900 回答
0

编写的方式printEvenOrOdd使其变得比需要的更困难。问题是它不打印单词“Even”或“Odd”,而是返回它,这意味着原件result丢失了。其余步骤依赖于实际数字。要解决此问题,您可以使用 callprintEvenOrOdd和 use.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()
);
于 2019-03-08T05:35:07.377 回答