为了账号安全,请及时绑定邮箱和手机立即绑定

这是在 java8 中使用 Nested groupby 的正确方法吗?

这是在 java8 中使用 Nested groupby 的正确方法吗?

开心每一天1111 2023-03-23 15:43:36
我有以下对象。class RowData{  private List<RowCell> cells;}class RowCell{  private String headerName;  private String value;}我已将以下 CSV 加载到这些对象中。Country,Gender,IncomeIND,M,23531IND,F,2331IND,M,2311SNG,M,22111HYD,F,20012我需要做什么 ?查找按国家和性别分组的平均收入。到目前为止我做了什么?List<String> criteria = Arrays.asList("Country", "Gender", "Income");List<RowData> rowDataStream = rows.stream().map(rowData -> new RowData(getMatchingCells(criteria, rowData))).collect(Collectors.toList());// group by countryMap<String, List<RowData>> collect = rowDataStream.stream().collect(groupingBy(rowData -> rowData.getRowCells().get(0).getValue()));// group everything above by gender now.Map<Map<String, List<RowData>>, List<List<RowData>>> collect1 = collect.values().stream().collect(groupingBy(rowData -> rowData.stream().collect(groupingBy(o -> o.getRowCells().get(1).getValue()))));问题这是正确的方法吗?这似乎过于复杂。你能建议一个更好的方法吗?
查看完整描述

3 回答

?
杨__羊羊

TA贡献1943条经验 获得超7个赞

首先,您可能应该将数据加载到有意义的 DTO/POJO 中:


class Row {

    String country;

    String gender;

    int income;

    // Getters etc.

}

然后,给定 a List<Row>,您可以简单地这样做:


Map<String, Double> groupedByCountry = list.stream().collect(

    Collectors.groupingBy(Row::getCountry, 

    Collectors.averagingInt(Row::getIncome)

)

Map<String, Double> groupedByGender = list.stream().collect(

    Collectors.groupingBy(Row::getGender, 

    Collectors.averagingInt(Row::getIncome)

)

Map<String, Map<String, Double>> groupedByCountryAndGender = list.stream().collect(

    Collectors.groupingBy(Row::getCountry, 

    Collectors.groupingBy(Row::getGender, 

    Collectors.averagingInt(Row::getIncome)

)

对于您给出的结构(RowData带有RowCells 的列表):


Map<String, Map<String, Double>> groupedByCountryAndGender = list.stream().collect(

    Collectors.groupingBy(r -> r.getCells().get(0).getValue(), 

    Collectors.groupingBy(r -> r.getCells().get(1).getValue(), 

    Collectors.averagingInt(r -> Integer.valueOf(r.getCells().get(2).getValue()))

)


查看完整回答
反对 回复 2023-03-23
?
紫衣仙女

TA贡献1839条经验 获得超15个赞

创建一个更符合逻辑的数据分组,例如:


class RowData {

    private String country;

    private String gender;

    private double income;


    // constructor, getters, setters

}

数据包含在以下列表中:


List<RowData> rowDataList = Arrays.asList(new RowData("IND", "M", 23531), 

                new RowData("IND", "F", 2331), new RowData("IND", "M", 2331),

                new RowData("SNG", "M", 22111), new RowData("HUD", "F", 20012));

现在你可以:


Map<String, Double> dataMap = rowDataList.stream()

              .collect(Collectors.groupingBy(e -> e.getCountry() + e.getGender(), 

                       Collectors.averagingDouble(RowData::getIncome)));


查看完整回答
反对 回复 2023-03-23
?
一只甜甜圈

TA贡献1836条经验 获得超5个赞

老实说,我正在看你的第二个groupBy,我不知道发生了什么。要立即按性别 + 国家/地区分组,我最好这样:

final Map<Pair<String, String>, List<RowData>> collect = rowDataStream.stream()
  .collect(groupingBy(rowData -> Pair.of(
        rowData.getCells().get(0).getValue(),
        rowData.getCells().get(1).getValue()
  )));

Pair 只是任何两个值的简单容器,您可以使用 apache commons pair、vavr tuple 或创建您自己的。


查看完整回答
反对 回复 2023-03-23
  • 3 回答
  • 0 关注
  • 113 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信