Groovy实现同coverageType数组元素分组到父元素子列表的方法
Groovy 数组分组结构化处理问题
我有一个数组列表,尝试用Groovy做结构化处理但没得到预期结果,使用putAll添加数组时会覆盖之前的数据,我的代码如下:
import java.util.stream.Collectors def fakeList = [ [coverageType: 'health', amount: 9, expireDate: 2020], [coverageType: 'insurance', amount: 10, expireDate: 2020], [coverageType: 'health', amount: 9, expireDate: 2021], ] def groupList = [:] def list = fakeList .stream() .map { item -> def parentWithChilds = [ parent: item.coverageType, child: groupList.stream() .map { list -> list?.parent !== item.coverageType } .collect(Collectors.toList()) ] groupList.putAll(parentWithChilds) }.collect(java.util.stream.Collectors.toList())
得到的输出是[parent:health, children:[true]],完全不符合预期。我需要把所有coverageType相同的元素归到对应父元素的子列表里,预期两种输出格式:
预期格式一:带键的子元素
[ [ parent: 'health', children: [ [ coverageType: 'health', amount:'9', expireDate: '2020' ], [ coverageType: 'health', amount:'9', expireDate: '2021' ], ] ], [ parent: 'insurance', children: [ [ coverageType: 'insurance', amount: '10', expireDate: '2020' ] ] ] ]
预期格式二:无键的子元素(仅保留值)
[ [ parent: 'health', children: [ ['health', '9', '2020'], ['health', '9', '2021'] ] ], [ parent: 'insurance', children: [ ['insurance', '10', '2020'] ] ] ]
解决方案
原代码逻辑混乱,没必要用Java Stream的复杂写法,Groovy原生的groupBy方法就能高效实现分组,再转换为目标结构即可。
实现格式一(带键子元素)
def fakeList = [ [coverageType: 'health', amount: 9, expireDate: 2020], [coverageType: 'insurance', amount: 10, expireDate: 2020], [coverageType: 'health', amount: 9, expireDate: 2021], ] // 按coverageType分组后转换为目标结构 def resultWithKeys = fakeList.groupBy { it.coverageType }.collect { type, items -> [ parent: type, children: items // 直接保留原元素的键值对列表 ] } println resultWithKeys
实现格式二(无键子元素)
def fakeList = [ [coverageType: 'health', amount: 9, expireDate: 2020], [coverageType: 'insurance', amount: 10, expireDate: 2020], [coverageType: 'health', amount: 9, expireDate: 2021], ] def resultWithoutKeys = fakeList.groupBy { it.coverageType }.collect { type, items -> [ parent: type, children: items.collect { item -> // 按顺序提取元素的值组成无键列表 [item.coverageType, item.amount.toString(), item.expireDate.toString()] } ] } println resultWithoutKeys
代码说明
groupBy { it.coverageType }:快速按coverageType分组,得到键为类型名、值为对应元素列表的Map。collect转换结构:遍历分组后的Map,将每个键值对映射为parent+children的结构。- 格式二中的
toString()用于将数字类型的amount和expireDate转为字符串,匹配预期输出格式;若不需要字符串类型,可直接去掉。
内容的提问来源于stack exchange,提问作者Fathe
相关产品推荐
相关产品推荐

