private void ensureCapacity(Stream<Currency> potentialCurrencies) { // If adding the currencies would mean we have more // currencies than matrix size, create an expanded array int requiredOrder = (int) Stream.concat(currencies.keySet().stream(), potentialCurrencies) .distinct() .count(); ensureCapacity(requiredOrder); }
private void addCurrencyPair(Currency ccy1, Currency ccy2, double rate) { // Only resize if there's a danger we can't fit a new currency in if (rates.length < currencies.size() + 1) { ensureCapacity(Stream.of(ccy1, ccy2)); } if (!currencies.containsKey(ccy1) && !currencies.containsKey(ccy2)) { // Neither currency present - add to disjoint set disjointRates.put(CurrencyPair.of(ccy1, ccy2), rate); } else if (currencies.containsKey(ccy1) && currencies.containsKey(ccy2)) { // We already have a rate for this currency pair updateRate(ccy1, ccy2, rate); } else { // We have exactly one of the currencies already addNewRate(ccy1, ccy2, rate); // With a new rate added we may be able to handle the disjoint retryDisjoints(); } }
/** * Adds a collection of new rates for currency pairs to the builder. * Pairs that are already in the builder are treated as updates to the * existing rates -> !e.getKey().equals(commonCurrency) && !currencies.containsKey(e.getKey()) * * @param rates the currency pairs and rates to be added * @return the builder updated with the new rates */ public FxMatrixBuilder addRates(Map<CurrencyPair, Double> rates) { ArgChecker.notNull(rates, "rates"); if (!rates.isEmpty()) { ensureCapacity(rates.keySet().stream() .flatMap(cp -> Stream.of(cp.getBase(), cp.getCounter()))); MapStream.of(rates).forEach((pair, rate) -> addRate(pair, rate)); } return this; }
private void retryDisjoints() { ensureCapacity(disjointRates.keySet() .stream() .flatMap(cp -> Stream.of(cp.getBase(), cp.getCounter()))); while (true) { int initialSize = disjointRates.size(); ImmutableMap<CurrencyPair, Double> addable = MapStream.of(disjointRates) .filterKeys(pair -> currencies.containsKey(pair.getBase()) || currencies.containsKey(pair.getCounter())) .toMap(); MapStream.of(addable).forEach((pair, rate) -> addNewRate(pair.getBase(), pair.getCounter(), rate)); addable.keySet().stream().forEach(disjointRates::remove); if (disjointRates.size() == initialSize) { // No effect so break out break; } } }