This sounds like a great addition! Naming is consistent with our existing methods.
Guillaume *Guillaume Laforge* Apache Groovy committer Developer Advocate @ Google Cloud <https://cloud.google.com/> - Blog: glaforge.dev - X: @glaforge <http://twitter.com/glaforge> - Bluesky: @glaforge.dev <https://bsky.app/profile/glaforge.dev> - Mastodon: @[email protected] <http://%[email protected]/> Le mer. 26 nov. 2025, 08:23, Paul King <[email protected]> a écrit : > Hi folks, > > I was recently looking at some of the functionality offered by Eclipse > Collections. One nice feature is its groupByEach method. It simplifies > using collectMany then groupBy. > > To fit in with Groovy naming, I think groupByMany is slightly better > in Groovy's case but the examples below show how current functionality > works (using collectMany/groupBy and then using groovy-ginq) and then > how be done using groupByMany: > > def citiesLived = [ > Alice: ['NY', 'LA'], > Bob: ['NY'], > Cara: ['LA', 'CHI'] > ] > > We want the reverse map of cities -> list of names: > > def grouped1 = citiesLived > .collectMany(e -> e.value.collect{ c -> [c, e.key] }) > .groupBy{ c, n -> c } > .collectEntries{ key, value -> [key, value*.get(1)] } > check(grouped1) > > Alternatively, we can use groovy-ginq: > > def grouped2 = GQL { > from n in citiesLived.keySet() > crossjoin c in citiesLived.values().sum().toSet() > where c in citiesLived[n] > groupby c > select c, list(n) > } > check(grouped2.collectEntries()) > > Here is what it looks like with the proposed method: > > def grouped3 = citiesLived.keySet().groupByMany { n -> citiesLived[n] } > check(grouped3) > > def check(grouped) { > assert grouped == [ > NY : ['Alice', 'Bob'], > LA : ['Alice', 'Cara'], > CHI : ['Cara'] > ] > } > > This is particularly useful for Eclipse Collections multimaps but maps > with lists are common enough in Groovy even without explicit multimaps > that I think this is valuable. You can think of it a little like the > "inverse" method of a BiMap implementation but instead of inverting K > and V we swap between K, List<V> to V, List<K>. > > Thoughts? I'll create a PR unless folks don't feel it adds enough > value or want to comment on the proposed functionality and naming. > > Cheers, Paul. >
