Как СУММИРОВАТЬ повторяющиеся ключевые значения в LinkedHashMap?

У меня есть LinkedHashMap, где у меня есть два повторяющихся ключа с соответствующими значениями, мне нужно знать, как СУММИРОВАТЬ эти значения в один ключ. В настоящее время он удаляет старое дублированное значение и ставит новое.

Это моя карта

static Map<String, Double> costByDuration = new LinkedHashMap<>();

Здесь я помещаю значения (call_from может быть 912345678 и иметь значение 10, а затем еще один вызов из 912345678 и иметь значение 20), затем я хочу, чтобы 912345678 имел значение 30 вместо сохранения только одного.

costByDuration.put(call_from, toPay);
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
527
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Используйте функцию слияние:

costByDuration.merge(call_from, toPay, (oldPay, toPay) -> oldPay + toPay);

что для вас oldPay?

José Nobre 07.06.2018 01:15
oldPay - это существующее значение, карта вычислит его автоматически. см. отредактированный ответ
Mạnh Quyết Nguyễn 07.06.2018 01:17
Ответ принят как подходящий

Сначала вам нужно будет проверить, есть ли ваше значение уже на карте.

Double existingValue = costByDuration.get(callFrom);
if (existingValue != null) {
    costByDuration.put(callFrom, existingValue + toPay);
}  else {
    costByDuration.put(callFrom, toPay);
}

Кстати, использовать Double для хранения суммы денег - плохая идея, если вы хотите, чтобы ваши арифметические операции давали вам правильный ответ. Я настоятельно рекомендую использовать BigDecimal вместо Double.

можно упростить с помощью Map::merge, но мне нравится +1 :)

Ousmane D. 07.06.2018 01:25

Я бы создал следующий метод:

public void put(String key, Double value){
    costByDuration.merge(key,value , Double::sum);
}

тогда вариант использования будет следующим:

put(call_from, toPay);
put(anotherKey, anotherValue);
...
...

Это решение внутренне использует метод merge, который в основном говорит, что если указанный ключ еще не связан со значением или связан с нулем, связывает его с заданным ненулевым значением. В противном случае заменяет связанное значение результатами заданной функции переназначения.

Хороший. И что интересно, у Double есть функциональная версия + (о которой я до сих пор не знал), но не -, *, / или %.

Dawood ibn Kareem 07.06.2018 01:29

@DawoodibnKareem, я предполагаю, что это дополнение является наиболее часто используемым, но, опять же, можно утверждать, что ему не хватает последовательности. Думаю, только авторы могут ответить ...

Ousmane D. 07.06.2018 01:34

Я бы, наверное, не стал называть метод put, потому что put, который сливается, а не заменяет, удивит будущих читателей. Возможно, addToTotal или любое другое имя подходит для вашего домена

Hulk 07.06.2018 09:50

@Hulk Хороший крик, спасибо !. Я не особо задумывался об именовании, когда публиковал ответ. Думаю, мы оставим это OP после того, как выберем лучшее имя, которое соответствует модели домена, как вы упомянули. :)

Ousmane D. 07.06.2018 10:12

Попробуйте это с помощью метода containsKey:

static Map<String, Double> costByDuration = new LinkedHashMap<>();
if (costByDuration.containsKey(call_from) { 
    costByDuration.put(call_from, map.get(call_from) + to_Pay);
} else {
    costByDuration.put(call_from, to_Pay);
}

Другие вопросы по теме