如何在Groovy中不修改变量实现列表单层扁平化?
Groovy 中扁平化嵌套列表一层的高效实现方式
问题场景
假设存在多层嵌套列表(示例如下),需要在不修改原变量的前提下,仅将列表扁平化一层:
List lists = [[[1]], [[2]], [[3]], [[4]], [[5]], [[6]], [[7]], [[8]], [[9]], [[10]]]
预期结果:
[[1], [2], [3], [4], [5], [6], [7], [8], [9], [10]]
要求实现的效率需接近以下基准代码:
lists.inject([]) { a, b -> a.addAll(b); a }
已知存在问题的实现方式
lists.flatten():会扁平化所有层级,最终得到[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],不符合仅扁平化一层的需求。lists.sum():写法简洁但时间复杂度为O(n²),效率无法满足要求。- Java Streams方式
lists.stream().flatMap(List::stream).toList():在Groovy中直接使用会有极大性能开销,即便用@CompileStatic包装能提升10-100倍性能,但操作不够便捷。
推荐的高效实现方案
1. 基准代码的简化写法
你给出的基准代码本身就是O(n)时间复杂度的高效实现,也可以简化为更简洁的Groovy风格写法:
lists.inject([]) { acc, item -> acc += item }
acc += item等价于acc.addAll(item)并返回累加器,效率和基准代码完全一致,语法更简洁。
2. 使用collectMany方法(Groovy 2.4+)
Groovy 2.4及以上版本原生提供了collectMany方法,专门用于将集合中的每个元素展开一层,内部实现为线性遍历收集,时间复杂度O(n),效率接近基准代码:
lists.collectMany { it }
这个写法直观简洁,是Groovy中处理这类需求的首选方式。
3. 指定层级的flatten(需注意空元素)
如果能确保原列表中没有null元素,也可以用指定层级的flatten方法:
lists.flatten(1)
flatten(1)参数表示仅扁平化一层,写法极其简洁,但如果列表中存在null元素会抛出NullPointerException,使用时需要注意元素的非空性。
内容的提问来源于stack exchange,提问作者IWilms
相关产品推荐
相关产品推荐

