async BankDatabase

Przykład rozwiązania do ćwiczenia niepunktowanego 4. z Programowania Współbieżnego.

public static CompletableFuture<Void> robinHoodAsync(Database db) {
return db.getAccountHoldersAsync()
.thenComposeAsync(holders -> {
var futures = holders.stream().map(holder ->
db.getAccountBalanceAsync(holder)
.thenApplyAsync(balance -> new SimpleEntry<>(holder, balance))
).toList();
return Utils.awaitAll(futures);
})
.thenApplyAsync(Utils::createMapFromEntries)
.thenComposeAsync(accounts -> {
Optional<Entry<String, Integer>> maybeRichest =
findTheRichestHolder(accounts);
if (maybeRichest.isEmpty())
return CompletableFuture.supplyAsync(() -> { return null; });
// lub krócej: return CompletableFuture.completedFuture(null);
Entry<String, Integer> richest = maybeRichest.get();
float value = richest.getValue() / (accounts.size() - 1)

var futures = accounts.keySet().stream().map(account -> {
if (account.equals(richest.getKey()))
return db.closeAccountAsync(account);
else
return db.addMoneyAsync(account, value);
}).toList();
return Utils.awaitAll(futures);
})
.thenRunAsync(() -> {});
}

W językach z konstrukcją await ten sam kod można napisać dużo krócej i bez nadmiernych zagnieżdżeń. Na przykład we współczesnym Javascripcie wyglądałoby to tak:

async function robinHood(db) {
let holders = await db.getAccountHolders();
let pairs = holders.map(async holder => [holder, await db.getAccountBalance(holder)]);
let accounts = new Map(await Promise.all(pairs));

let richest = findTheRichestHolder(accounts);
if (richest === null)
return;
let value = richest.value / (accounts.size - 1)

let promises = Array.from(accounts.keys()).map(holder =>
holder === richest.holder
? db.closeAccount(holder)
: db.addMoney(holder, value)
);
await Promise.all(promises);
}