0

I have this data structure with some example content:

List<Set<Character>> aList = List.of(Set.of('a', 'b', 'c'), Set.of('a', 'b', 'c'), Set.of('a', 'b', 'c'), Set.of('a'), Set.of('b'));

I would like to retrieve the sum of all characters. In this example, it would be

3 + 3 + 3 + 1 + 1 = 11

I can solve this like that:

int sum = 0;
for (Set<Character> aSet : aList) {
   sum += aSet.size();
}

But, I am almost certainly sure there's a smarter way of doing this with a stream. I just can't figure it out. Does anyone has an idea?

Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
diskostu
  • 143
  • 1
  • 11
  • diskostu, I know this is kinda too big for a one liner, but did not want to add an answer when this covers the big picture rather than the particular question. `Arrays.stream(input.split("\n\n")).mapToInt(group -> (int) IntStream.rangeClosed('a', 'z').filter(c -> Arrays.stream(group.split("\n")).anyMatch(entry -> entry.indexOf((char) c) >= 0)).count()).sum();` d6p2 uses the same snippet but it it involves `c -> Arrays.stream(splitted.split("\n")).allMatch(` rather than `anyMatch` :) – dbl Dec 07 '20 at 15:58

2 Answers2

2

You should map the sets to their sizes and then you can apply sum():

aList.stream().mapToInt(p -> p.size()).sum();

Or as suggested by khelwood:

aList.stream().mapToInt(Set::size).sum();
jmizv
  • 1,172
  • 2
  • 11
  • 28
  • 2
    or even `Set::size` – khelwood Dec 07 '20 at 14:07
  • `even better` - yeah, probably; that certainly feels more idiomatic. `more precise` - what? There's nothing 'more precise' about it. It's the same code, the one and only difference is a style debate of which form 'looks better'. – rzwitserloot Dec 07 '20 at 14:28
  • 2
    Or even `Collection::size` for more generalised use. – Bohemian Dec 07 '20 at 15:02
  • @rzwitserloot what you say is not true. Method reference (e.g. `X::prop`) will not create a new anonymous method, instead it will execute the one being pointed. On the other hand, lambda `x -> x.prop()` will create a new anonymous method and execute that one instead. Based on [this answer](https://stackoverflow.com/questions/27524445/does-a-lambda-expression-create-an-object-on-the-heap-every-time-its-executed/27524543#27524543). – dbl Dec 07 '20 at 15:08
  • "will not create a new anonymous method, instead it will execute the one being pointed." This has nothing to do with the word 'precise'. Had you said more 'efficient', I think we can nitpick what that word means, but at least it's applicable. – rzwitserloot Dec 07 '20 at 15:38
  • I did not mean **more "efficient"** or anything, just wanted to be more specific on the topic. Based on [this answer](https://stackoverflow.com/a/24493905/2185630). – dbl Dec 07 '20 at 15:44
  • @rzwitserloot Whooops, it seems that I'm totally wrong about it. Just had the time to dig into the pointed Holger answer and reach [this brilliant answer](https://stackoverflow.com/questions/23983832/is-method-reference-caching-a-good-idea-in-java-8/23991339#23991339) of his. Method refs do create new anonymous... – dbl Dec 08 '20 at 00:44
-1
aList.stream().map(Set::size).reduce(0, Integer::sum)

first you map the list to the size and then you reduce using sum with 0

  • Can you please explain why downvoted this answer, even though I have an idea why... – dbl Dec 07 '20 at 14:41
  • I wonder why too? I was responding and then apparently someone responded before :D – Luis Ramirez-Monterosa Dec 07 '20 at 15:00
  • 2
    I can guess: It’s a poor implementation. Converting to an `IntStream` and summing is idiomatic and superior in every way. – Bohemian Dec 07 '20 at 15:01
  • 1
    I thought downvotes were for really bad answers not for not perfect ones, whatever floats their boat to be honest as I don't care about my rep but still is not like the worst solution – Luis Ramirez-Monterosa Dec 07 '20 at 15:04
  • 1
    @dbl Floating with your mouse over the downvote button expains what it is for: "This answer is not useful". It does not read "This answer is really bad". This answer's entire point is to just show the answer (it does not include context or explanations, which is fine, not all answers need that), but as it is just a basic 'this is how to do it' answer, given that this isn't the idiomatic way, it's not useful. It doesn't really teach the asker about concepts and shows them a suboptimal solution. – rzwitserloot Dec 07 '20 at 15:37