Добавьте BigDecimals в Map, сопоставляя с ключами из другого набора - PullRequest
0 голосов
/ 28 мая 2018

У меня есть Карта с номерами продаж, разделенными на год:

Map<Integer, BigDecimal> sales_by_year = new TreeMap<>();
sales_by_year.put(2012, BigDecimal.valueOf(19283));
sales_by_year.put(2013, BigDecimal.valueOf(24832));
sales_by_year.put(2014, BigDecimal.valueOf(19562));
sales_by_year.put(2015, BigDecimal.valueOf(21879));
sales_by_year.put(2016, BigDecimal.valueOf(23587));
sales_by_year.put(2017, BigDecimal.valueOf(28756));

и список, по каким годам я хочу добавить эти продажи:

Set<Integer> years = new HashSet<>(Arrays.asList(new Integer[] {2012, 2013, 2014}));

, и я хочунаписать лямбду, чтобы объединить эти годы в один BigDecimal.Я написал это:

BigDecimal sales_for_timeframe = sales_by_year.entrySet().stream()
        .filter(a -> years.contains(a.getKey()))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
        .values().stream()
        .reduce(BigDecimal.ZERO, BigDecimal::add);

System.out.println(sales_for_timeframe);

и это работает.Но это самый эффективный способ?Это решение:

  1. Преобразует карту в поток
  2. Фильтрует карту
  3. Собирает ее обратно в новую карту
  4. Преобразует новую картуvalueSet в поток
  5. Уменьшает значения до одного BigDecimal

Есть ли способ уменьшить количество шагов?Повысит ли это эффективность?Или это лучшее решение?

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

Следующее было бы более эффективным, потому что:

  • Нет промежуточной коллекции
  • Повторение меньшего набора years вместо большего sales_by_year map
BigDecimal sales_for_timeframe = years.stream()
        .map(yr -> sales_by_year.getOrDefault(yr, BigDecimal.ZERO))
        .filter(bd -> bd.signum() != 0) // prevent unnecessary adds (optional)
        .reduce(BigDecimal.ZERO, BigDecimal::add);

В более раннем редакторе ответ от jspcal имел эту альтернативную реализацию, полностью используя ссылки на методы:

BigDecimal sales_for_timeframe = years.stream()
        .map(sales_by_year::get)
        .filter(Objects::nonNull)
        .reduce(BigDecimal.ZERO, BigDecimal::add);
0 голосов
/ 28 мая 2018

Вы можете немного его укоротить:

BigDecimal sum = years.stream()
    .map(y -> sales_by_year.getOrDefault(y, BigDecimal.ZERO))  
    .reduce(BigDecimal.ZERO, BigDecimal::add);
...