Farrukh Chishti
Farrukh Chishti

Reputation: 8437

How to create a map with sum of all specific objects?

I have an object:

class Sample
{
    String currency;
    String amount;
}

I want an output map with sum of all objects of a specific currency.

Example-

Pointer. I have been working with the following code but its not working as I expected. You can use this code as reference:

Map<String, Double> finalResult = samples
        .stream()
        .collect(Collectors.toMap(
                Sample::getCurrency,
                e -> e.getAmount()
                      .stream()
                      .sum()));

Upvotes: 0

Views: 780

Answers (3)

WJS
WJS

Reputation: 40034

Just wanted to offer the following alternative for future consideration. I am also presuming you meant double for the amount as well as having the appropriate getters. You could have used Collectors.toMap as long as you included a merge function. It looks like you had the right idea but the wrong syntax.

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));

The third argument to toMap is a merge function to properly handle duplicates. In this cases it computes a sum of the values for each key as they are encountered.

Map<String, Double> result = samples.stream()
           .collect(Collectors.toMap(
                 Sample::getCurrency, Sample::getAmount, Double::sum));

result.entrySet().forEach(System.out::println);

prints

EUR=70.0
USD=40.0
INR=130.0

If you really want your class to store the amount as a String, you can replace Sample::getAmount with sample->Double.valueOf(sample.getAmount()) to convert the String to a Double. But since you will probably be using these values repeatedly in computations, it is best, imo, to store the amount in its most frequently used form when the class instances are created.

Upvotes: 4

xwine
xwine

Reputation: 91

Map<String, Double> finalResult = samples.stream().collect(
    Collectors.groupingBy(
          (Sample::getCurrency),
          Collectors.summingDouble(
             sample -> { return Double.parseDouble(sample.getAmount()); 
})));

Upvotes: 2

Youcef LAIDANI
Youcef LAIDANI

Reputation: 59960

You need to use groupingBy with summingDouble and not toMap:

Map<String, Double> finalResult = samples
        .stream()
        .collect(Collectors.groupingBy(
                Sample::getCurrency,
                Collectors.summingDouble(Sample::getAmount)
        ));

I consider amount is of type Double and your example is not correct (String amount;)

Upvotes: 5

Related Questions