【问题标题】:Chaining completable futures based on conditions根据条件链接可完成的期货
【发布时间】:2019-03-08 04:24:56
【问题描述】:

我有一堆返回 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找到最近的偶数

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

【问题讨论】:

    标签: java asynchronous exception completable-future conditional-execution


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      printEvenOrOdd 的编写方式使其变得比实际需要的更加困难。问题是它没有打印单词“Even”或“Odd”,而是返回它,这意味着原来的result 丢失了。其余步骤依赖于实际数字。要解决此问题,您可以调用 printEvenOrOdd 并在之后使用 .thenApply(__ -&gt; 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()
      );
      

      【讨论】:

        猜你喜欢
        • 2023-02-16
        • 2016-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-16
        • 2015-05-17
        • 2022-11-04
        相关资源
        最近更新 更多