-3

Is there a simple/elegant way of summing numbers in a list for every key in the map, e.g. from Map<String, List<BigDecimal>> I want to get Map<String, BigDecimal>? I couldn't find it/figure it out...

user2340939
  • 1,791
  • 2
  • 17
  • 44
  • reducing... being adding them? – Eugene Aug 14 '18 at 13:37
  • Reduce = sum. I've edited the question. I used reduction since it could be some other operation than summation. – user2340939 Aug 14 '18 at 13:39
  • 3
    @YCF_L: how do you get to 30K and still hold that opinion? I don't know who has downvoted on this page, but votes are anonymous by design and do not need to be justified. That has been established on _Meta_ many times, and there would need to be a substantial policy change to require voters to justify their votes. – halfer Aug 14 '18 at 15:13
  • 1
    Both answers are mostly code and without any real explanation of the problem or their solution, and in this situation while they may help the original poster they are certainly not going to help any future visitors to this site with a similar problem and could qualify for down-votes based on that alone. – Hovercraft Full Of Eels Aug 14 '18 at 15:18
  • (Remember that as a high-rep user, other SO users will look to you as an exemplar of policy, and so it doesn't help "janitor" volunteers if newer users are encouraged to take on plainly wrong views about how the site works.) – halfer Aug 14 '18 at 15:18
  • @HovercraftFullOfEels NO you are wrong in this I can gives you hundreds of answer which is like my answer and Eugen's answer take a look https://stackoverflow.com/questions/157944/create-arraylist-from-array https://stackoverflow.com/questions/363681/how-do-i-generate-random-integers-within-a-specific-range-in-java https://stackoverflow.com/questions/1066589/iterate-through-a-hashmap https://stackoverflow.com/questions/46898/how-to-efficiently-iterate-over-each-entry-in-a-map https://stackoverflow.com/questions/5585779/how-do-i-convert-a-string-to-an-int-in-java there are more – Youcef LAIDANI Aug 14 '18 at 16:24
  • 2
    @YCF_L: As I tell my kids, the excuse that "... but Billy's mom let's him do it" is not a valid one. Regardless of whether or not other answers on this site are code only answers does not make your answer good. The explanation is key, and your answers contain none. – Hovercraft Full Of Eels Aug 14 '18 at 16:26
  • 1
    @YCF_L But why are you debating the issue rather than improving the answer? What do you lose by improving it? What does the site gain? – Hovercraft Full Of Eels Aug 14 '18 at 16:27
  • 2
    @YCF_L those are extremely old answers. Times have changed. Nowadays, code only answers without explanation are discouraged. – Modus Tollens Aug 14 '18 at 16:28
  • 1
    Why the downvotes? I had a *specific* question, and I got specific answers... – user2340939 Aug 17 '18 at 11:37

2 Answers2

10

To change from Map<String, List<BigDecimal>> to Map<String, BigDecimal> there are two steps :

First step : use Collectors.toMap to take the keys of the old map to the new map.

Second step : you have to sum all the elements of your List<BigDecimal> there are many ways one of them is to use e.getValue().stream().reduce(BigDecimal.ZERO, BigDecimal::add)

In the end your code can look like this :

Map<String, BigDecimal> result = map.entrySet().stream()
        .collect(Collectors.toMap(
                Map.Entry::getKey, 
                e -> e.getValue().stream().reduce(BigDecimal.ZERO, BigDecimal::add))
        );

Ideone example

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • you want to do it with `.reduce(BigDecimal::add).orElse(BigDecimal.ZERO)` most probably... and we both got a down vote :) nice – Eugene Aug 14 '18 at 13:49
  • @Eugene Both `reduce(BigDecimal.ZERO, BigDecimal::add)` and `reduce(BigDecimal::add).orElse(BigDecimal.ZERO)` give the same result (the sum or zero if the stream was empty). – Slaw Aug 14 '18 at 14:09
  • @Slaw of course they do, that was not the point – Eugene Aug 14 '18 at 14:10
  • @Eugene Then I'm missing the point..? Was it just sarcasm related to the downvotes? – Slaw Aug 14 '18 at 14:10
  • 2
    @Eugene Nope... not sure what you're getting at. Both strategies (as far as I understand) are virtually identical; especially in this case. The only difference I can spot is that using `reduce` without an identity causes the creation of an unnecessary `Optional`. Now, if the identity was a complex computation then I could understand using the `Optional`-returning-overload along with `orElseGet(Supplier)`. (p.s. I'm sorry if I'm completely misunderstanding you) – Slaw Aug 14 '18 at 14:31
  • @Eugene The argument for `orElse` is _always_ evaluated regardless of the state of the `Optional`. – Slaw Aug 14 '18 at 14:44
  • @Slaw I need to stop commenting on 10 posts at a time... I'll update shortly. sorry – Eugene Aug 14 '18 at 14:47
  • 1
    @Slaw this matters when there is a single element in the stream (under the current implementation - no idea if this will matter in any other future one). Suppose there is a Stream with a single element. when you use `reduce(BigDecimal::add)` that function will be called only when there are more than one elements, otherwise that element will be returned, so that would make it a super tiny optimization – Eugene Aug 15 '18 at 11:07
  • @Eugene Interesting (edge case?) and makes sense. Both create a new unnecessary object: a `BigDecimal` from `add` and an `Optional` from the non-identity `reduce`. Both do a computation: `BigDecimal.add` and `Optional.orElse`. I suppose it comes down to which object is more expensive to create and which computation is more expensive. I'm leaning towards your strategy being the _tiniest_ more efficient. This leads me to suspect worrying about this in this case is the epitome of premature optimization. – Slaw Aug 15 '18 at 12:50
  • @Slaw two things 1) it got under my skin already, so I use it without thinking (thus the slow delay on my comment, I had to remember why I actually use it like this) 2) *epitome* - no idea this existed (I am non-english native speaker to begin with), thank u – Eugene Aug 15 '18 at 13:13
2
map.entrySet()
            .stream()
            .collect(Collectors.toMap(
                    Entry::getKey,
                    x -> x.getValue().stream()
                                     .reduce(BigDecimal::add)
                                     .orElse(BigDecimal.ZERO)));
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
Eugene
  • 117,005
  • 15
  • 201
  • 306