Reputation: 2618
I am having a bunch of methods that return a CompletableFuture and I would like to chain in a specific way
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;
});
}
}
I am trying to combine them based on the following rules,
Even
, if it is odd print Odd
findFactorial
with the random numberconvertToNearestEvenInteger
I am not too clear on how to do the conditional chaining and exception handling. Some examples or code snippets may be helpful.
Upvotes: 3
Views: 3405
Reputation: 361605
The way printEvenOrOdd
is written makes it more difficult than it needs to be. The problem is that it doesn't print the word "Even" or "Odd", it returns it, which means the original result
is lost. The rest of the steps rely on having the actual number. To work around it, you could use call printEvenOrOdd
and use .thenApply(__ -> result)
to restore the original number afterwards. It would look like this:
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()
);
A better solution would be to change the definition of printEvenOrOdd
to something like:
public CompletableFuture<Integer> printEvenOrOdd(int result) {
return CompletableFuture.supplyAsync(() -> {
System.out.println(result % 2 == 0 ? "Even" : "Odd");
return result;
});
}
That would make it much easier to chain steps 3 and 4:
System.out.println(
generateRandom(1, 100)
.thenApply(this::printEvenOrOdd)
.thenCompose(result ->
result % 2 == 0
? findFactorial(result)
: convertToNearestEvenInteger(result)
)
.join()
);
Upvotes: 0
Reputation: 7917
You can use 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());
However, when big even numbers are generated, your factorial method can't store anything bigger than int
, so you need to update that.
Upvotes: 3