我有一个如下所示的数据列表:
List<Data> data = new ArrayList<Data>();
data.add(new Data("d1", "option1"));
data.add(new Data("d2", "option1"));
data.add(new Data("d1", "option2"));
data.add(new Data("d3", "option1"));
data.add(new Data("d3", "option2"));
data.add(new Data("d3", "option3"));
结构如下:
class Data {
private String name;
private String option;
private List<String> options = new ArrayList<>();
public Data(String name, String option) {
this.name = name;
this.option = option;
}
public void addOption(String option) {
options.add(option);
}
}
如何根据名称及其选项
将项目分组到新阵列[
"d1": {
"name": "d1",
"options": ["option1", "option2"]
},
"d2": {
"name": "d2",
"options": ["option1"]
},
"d3": {
"name": "d3",
"options": ["option1", "option2", "option3"]
}
]
答案 0 :(得分:2)
您可以使用Collectors.toMap
收藏家:
Map<String,Data>
grouped = data.stream()
.collect(Collectors.toMap(Data::getName,
d -> new Data(d.getName(),d.getOption()),
(d1,d2) -> {d1.addOptions(d2.getOptions()); return d1;});
这需要更改Data
构造函数,将传递的选项添加到选项List
,并添加一个addOptions
方法,该方法接收选项列表并将所有选项添加到当前实例的选项List
。
答案 1 :(得分:1)
试试这个,
final Map<String, List<String>> optionsByName = dataList.stream().collect(
Collectors.groupingBy(Data::getName, Collectors.mapping(Data::getOption, Collectors.toList())));
我建议您使用此map
作为创建所需DTO的来源,而不会使代码混乱,以获得您想要的确切结果。
答案 2 :(得分:1)
您可以在流上使用简单的分组收集器:
Map<String, List<String>> optionMap = data.stream()
.collect(Collectors.groupingBy(Data::getName,
Collectors.mapping(Data::getOption, Collectors.toList())));
使用测试列表进行测试时,上面会生成此输出:
{d1=[option1, option2], d2=[option1], d3=[option1, option2, option3]}
上述内容似乎是您所需地图的更好,类型安全的替代方案。此外,它避免了不必要的重复。
您的最终地图仍然可以根据以上内容计算:
Map<String, Map<String, Object>> m = new HashMap<>();
optionMap.entrySet().forEach(entry -> {
Map<String, Object> map = new HashMap<>();
map.put("name", entry.getKey());
map.put("options", entry.getValue());
m.put(entry.getKey(), map);
});
上面的m
地图如下所示:
{d1={name=d1, options=[option1, option2]},
d2={name=d2, options=[option1]},
d3={name=d3, options=[option1, option2, option3]}}
这就是您所需要的,但它似乎包含重复数据,并且它比以前结果中的简单地图更不便于类型安全。