There are 2 services:
How can I group result by id1 -> [id2, id2, id2, ...]
using CompletableFuture
?
I was thinking to put it all to the HashMap but I don't understand how to pass ids1 to the second Future. I was thinking of using thenCombine(ids1Future, (v1, v2) -> {...})
, but it seems quite ugly to me. Are there any "best practices" to do it?
Here is not async way:
Map<ID1, List<ID2>> idsMap = new HashMap();
List<IDS1> ids1List = service1.service.find();
for (ID1 id1: IDS1) {
List<IDS2> ids2List = service2.findById(id1);
idsMap.put(id1, ids2List);
}
service2.process(idsMap);
Trying to do it async:
CompletableFuture<List<IDS1>> ids1Future
= CompletableFuture.supplyAsync(() -> service.find());
ids1Future.thenApply((ids1) -> {
CompletableFuture<List<IDS2>> listFutureIds2
= ids1.stream().map(id1
-> CompletableFuture.supplyAsync(()
-> service2.getById(id1)))
.collect(Collectors.toList());
CompletableFuture<Void> allFuturesDone
= CompletableFuture.allOf(
listFutureIds2.toArray(
new CompletableFuture[listFutureIds2.size()]));
allFuturesDone.thenApply(v
-> list.stream()
.map(CompletableFuture::join)
.collect(toList()));
});
This is an example of how to use Fork/Join to convert a list of chars to a list of strings, where each string is a replication of N times of the char. You can adjust this example to your case.
I hope that this is what you are looking for.
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.Collectors;
public class ForkJoinExample {
public static class RepeatTask extends RecursiveTask<List<String>> {
private final List<Character> chars;
private final int repeatCount;
public RepeatTask(List<Character> chars, int repeatCount) {
this.chars = chars;
this.repeatCount = repeatCount;
}
public RepeatTask(Character c, int repeatCount) {
this.chars = List.of(c);
this.repeatCount = repeatCount;
}
@Override
protected List<String> compute() {
if (chars.size() > 1) {
ForkJoinTask.invokeAll(chars.stream().map(c -> new RepeatTask(c, repeatCount)).collect(Collectors.toList()));
return ForkJoinTask.invokeAll(chars.stream().map(c -> new RepeatTask(c, repeatCount)).collect(Collectors.toList()))
.stream()
.map(ForkJoinTask::join)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
return List.of(String.valueOf(chars.get(0)).repeat(Math.max(0, repeatCount)));
}
}
public static void main(String[] args) {
ForkJoinPool commonPool = ForkJoinPool.commonPool();
RepeatTask task = new RepeatTask(List.of('a', 'b', 'c'), 4);
commonPool.execute(task);
System.out.println(task.join());
}
}
The result is this one: [aaaa, bbbb, cccc]
I hope I understood you correctly, so here it is:
CompletableFuture<List<IDS1>> ids1Future = CompletableFuture.supplyAsync(service::find);
CompletableFuture<Map<IDS1, List<IDS2>>> map = ids1Future.thenApply(listIDS1 -> {
List<Entry<IDS1, CompletableFuture<List<IDS2>>>> list =
listIDS1
.stream()
.map(ids1 -> new SimpleEntry<>(ids1, CompletableFuture.supplyAsync(() -> service2.getById(ids1))))
.collect(Collectors.toList());
return list.stream()
.map(entry -> new SimpleEntry<>(entry.getKey(), entry.getValue().join()))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
});
Map<IDS1, List<IDS2>> result = map.join();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.