countBy
Tallies how many elements map to each computed key.
Lecture
countBy completes the trio with
groupBy and
indexBy: same idea of pulling the
whole pipeline and computing a key per element, but this time it doesn't
keep the elements at all — it just increments a counter per key. The
result is a Map<K, int>: how many elements produced
each key.
Think of the three as answering different questions about the same
grouping: groupBy — "give me every element for this key",
indexBy — "give me the last element for this key", and
countBy — "how many elements had this key?" If all you need
is the tally, countBy is cheaper than
groupBy(...).map((k, v) => MapEntry(k, v.length)) since it
never allocates the intermediate lists.
It is also cheaper than the loop you would write instead. The obvious
version, counts[k] = (counts[k] ?? 0) + 1, touches the hash map
twice per element — once to read, once to write back — and
when all you are doing is counting, the map is essentially the whole cost.
countBy counts into a mutable cell held in the map, so the map
is written once per distinct key instead of once per element:
about 1.5× faster than the hand loop on a million
elements, and the margin holds from a handful of keys up to tens of
thousands. Most frequent log
level works the number through end to end.
As always, it's a terminal — nothing upstream runs until countBy pulls it.
Demo 1 · Basics
Demo 2 · Async
Try it yourself
Exercise: count how many votes each candidate received.