Суммирование BigDecimals в потоках API Collectors - PullRequest
0 голосов
/ 20 января 2019

Моя текущая попытка основана на членах класса двойного типа:

public Client whoPaidTheMost() {

/*METHOD EXPLOITING STREAM API*/

return shopping.entrySet()
        .stream()
        .collect(Collectors.groupingBy(Map.Entry::getKey,
                Collectors.flatMapping(e -> e.getValue().entrySet().stream(),
                        Collectors.summingDouble(e->e.getKey().getPrize() * e.getValue())))) /*should be refactored*/
        .entrySet().stream()
        .max(Comparator.comparingDouble(Map.Entry::getValue))/*should be refactored*/
        .get()
        .getKey();
}

покупки - это, в основном, карта: Map<Client, Map<Product,Integer>>,

  • Внешний ключ представляет Клиента
  • Внутренний Ключ представляет Продукт
  • значение внутренних карт (целое число) представляет номер указанного продукта, принадлежащего конкретному клиенту

Товар члены класса имя, категория, цена (ранее двойного типа) - хотите преобразовать предоставленный код в код, используя цену в качестве типа BigDecimal

Как я могу заставить этот код работать и для BigDecimals -?

По сути, я рефакторинг этого арлеади:

  Client client = shopping.entrySet()
            .stream()
            .collect(Collectors.groupingBy(Map.Entry::getKey,
                    Collectors.flatMapping(e -> e.getValue().entrySet().stream(),
                            Collectors.mapping(e -> BigDecimal.valueOf(new Long(e.getValue())).multiply(e.getKey().getPrize()),
                                    Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)))))
            .entrySet().stream()
            .max((e1, e2) -> (e1.getValue().compareTo(e2.getValue())))
            .get()
            .getKey();

Все еще задаетесь вопросом, возможно ли это изменить, не используя: Collectors.mapping(e -> BigDecimal.valueOf(new Long(e.getValue())).multiply(e.getKey().getPrize()) до Collectors.reducing?

Ответы [ 2 ]

0 голосов
/ 20 января 2019

Вы можете сделать рефакторинг следующим образом:

shopping.entrySet().stream()
    .collect(
        Collectors.groupingBy(Map.Entry::getKey,
            Collectors.flatMapping(
                e -> e.getValue().entrySet().stream()
                    .map(innerEntry -> innerEntry.getKey().getPrice()
                    .multiply(BigDecimal.valueOf(innerEntry.getValue()))),
            Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))))
    .entrySet().stream()
    .max(Map.Entry.comparingByValue()).get().getKey();

Вам не нужно никаких дополнительных mapping Collector здесь.Просто используйте оператор map, чтобы преобразовать ваш Map.Entry в BigDecimal на основе ваших вычислений, и передайте это Stream<BigDecimal> вниз.Финальный оператор сокращения делает свое дело здесь.Ноль действует как хороший элемент идентичности для этой суммы.

0 голосов
/ 20 января 2019

Если вы ищете Collector с суммой BigDecimal с, это должно работать:

Collector<BigDecimal, ?, BigDecimal> collector 
    = Collectors.reducing(BigDecimal.ZERO, BigDecimal::add);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...