按对象分组 - Java流

时间:2018-05-30 06:20:25

标签: java collections java-8 java-stream

我有一个如下所示的数据列表:

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"]
}
]

3 个答案:

答案 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]}}

这就是您所需要的,但它似乎包含重复数据,并且它比以前结果中的简单地图更不便于类型安全。