Imagine a list of lists, for example
List lists = [[[1]], [[2]], [[3]], [[4]], [[5]], [[6]], [[7]], [[8]], [[9]], [[10]]]
This is just an example - the inner lists may contain multiple elements. I want to flatten the list by one level without mutating variables. The result should be
[[1], [2], [3], [4], [5], [6], [7], [8], [9], [10]]
Is there a good way in Groovy for that? It should be almost as fast as
lists.inject([]) { a, b -> a.addAll(b); a }
lists.flatten()
flattens across all levels, resulting in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
.lists.sum()
is concise and does the job, but sadly in O(n2) for this case. It should be done in O(n).lists.stream().flatMap(List::stream).toList()
seems to be O(n) in Groovy, but I was'nt so sure at first as it apparently comes with an extreme overhead compared to using it directly in Java. You can speed it up by a factor of 10 to 100 by just wrapping it in a method using @CompileStatic
. Then it would be fast, but that is not really a convenient solution. There must be another way.Ah, apparently that is what lists.collectMany { it }
is for...
collectMany()
is a bit like flatMap
in Scala or Java Streams.
It does not mutate variables at top level and is reasonably fast:
Not as fast as
lists.inject([]) { a, b -> a.addAll(b); a }
but much faster than
lists.stream().flatMap(List::stream).toList()
I have played around with it and collectMany()
is more powerful than the standard flatMap
and pretty cool to use, also for concatenating Maps.