#java #collections #java-8 #java-stream
Вопрос:
У меня есть объект:
class Sample
{
String currency;
String amount;
}
Мне нужна выходная карта с суммой всех объектов определенной валюты.
Пример-
- INR 40
- 80 долларов США
- 20 ЕВРО
Указатель. Я работал со следующим кодом, но он работает не так, как я ожидал. Вы можете использовать этот код в качестве ссылки:
Map<String, Double> finalResult = samples
.stream()
.collect(Collectors.toMap(
Sample::getCurrency,
e -> e.getAmount()
.stream()
.sum()));
Комментарии:
1. Не уверен, в чем заключается ваш реальный вопрос. «Возможное решение» звучит так, как будто у вас уже есть ответ? Если у вас возникли проблемы, пожалуйста, добавьте их в вопрос.
2. @Марвин : Это скорее указатель на решение. Что-то, что я пробовал, но не получилось полностью.
Ответ №1:
Вам нужно использовать groupingBy
с summingDouble
и не toMap
:
Map<String, Double> finalResult = samples
.stream()
.collect(Collectors.groupingBy(
Sample::getCurrency,
Collectors.summingDouble(Sample::getAmount)
));
Я считаю, что сумма имеет тип Double
, и ваш пример неверен ( String amount;
)
Комментарии:
1. Хороший ответ, так что 1. Однако
toMap
работает с третьим аргументомDouble::sum
, который я продемонстрировал в своем альтернативном ответе.2. хороший @WJS, я не знал об этом раньше
Ответ №2:
Просто хотел предложить следующую альтернативу для дальнейшего рассмотрения. Я также предполагаю, что вы имели double
в виду сумму, а также наличие соответствующих получателей. Вы могли бы использовать Collectors.toMap
, если бы включили a merge function
. Похоже, у вас была правильная идея, но неправильный синтаксис.
List<Sample> samples =
List.of(new Sample("USD", 10), new Sample("USD", 30),
new Sample("INR", 40), new Sample("INR", 90),
new Sample("EUR", 20), new Sample("EUR", 50));
Третий аргумент toMap
-это a merge function
для правильной обработки дубликатов. В этом случае он вычисляет сумму значений для каждого ключа по мере их обнаружения.
Map<String, Double> result = samples.stream()
.collect(Collectors.toMap(
Sample::getCurrency, Sample::getAmount, Double::sum));
result.entrySet().forEach(System.out::println);
С принтами
EUR=70.0
USD=40.0
INR=130.0
Если вы действительно хотите , чтобы ваш класс хранил сумму как a String
, вы можете Sample::getAmount
заменить sample->Double.valueOf(sample.getAmount())
ее на преобразование String
в a Double
. Но поскольку вы, вероятно, будете повторно использовать эти значения в вычислениях, имо, лучше всего хранить сумму в наиболее часто используемой форме при создании экземпляров класса.
Ответ №3:
Map<String, Double> finalResult = samples.stream().collect(
Collectors.groupingBy(
(Sample::getCurrency),
Collectors.summingDouble(
sample -> { return Double.parseDouble(sample.getAmount());
})));
Комментарии:
1.ввод :
( INR 40 USD 80 EUR 20), (INR 0 USD 100 EUR 100 )
</br> </br>результат{EUR=120.0, USD=180.0, INR=40.0}