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

我有以下对象。


class RowData

{

  private List<RowCell> cells;

}


class RowCell

{

  private String headerName;

  private String value;

}

我已将以下 CSV 加载到这些对象中。


Country,Gender,Income

IND,M,23531

IND,F,2331

IND,M,2311

SNG,M,22111

HYD,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 country

Map<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()))));

问题

  1. 这是正确的方法吗?

  2. 这似乎过于复杂。你能建议一个更好的方法吗?


开心每一天1111
浏览 117回答 3
3回答

杨__羊羊

首先,您可能应该将数据加载到有意义的 DTO/POJO 中:class Row {&nbsp; &nbsp; String country;&nbsp; &nbsp; String gender;&nbsp; &nbsp; int income;&nbsp; &nbsp; // Getters etc.}然后,给定 a List<Row>,您可以简单地这样做:Map<String, Double> groupedByCountry = list.stream().collect(&nbsp; &nbsp; Collectors.groupingBy(Row::getCountry,&nbsp;&nbsp; &nbsp; Collectors.averagingInt(Row::getIncome))Map<String, Double> groupedByGender = list.stream().collect(&nbsp; &nbsp; Collectors.groupingBy(Row::getGender,&nbsp;&nbsp; &nbsp; Collectors.averagingInt(Row::getIncome))Map<String, Map<String, Double>> groupedByCountryAndGender = list.stream().collect(&nbsp; &nbsp; Collectors.groupingBy(Row::getCountry,&nbsp;&nbsp; &nbsp; Collectors.groupingBy(Row::getGender,&nbsp;&nbsp; &nbsp; Collectors.averagingInt(Row::getIncome))对于您给出的结构(RowData带有RowCells 的列表):Map<String, Map<String, Double>> groupedByCountryAndGender = list.stream().collect(&nbsp; &nbsp; Collectors.groupingBy(r -> r.getCells().get(0).getValue(),&nbsp;&nbsp; &nbsp; Collectors.groupingBy(r -> r.getCells().get(1).getValue(),&nbsp;&nbsp; &nbsp; Collectors.averagingInt(r -> Integer.valueOf(r.getCells().get(2).getValue())))

紫衣仙女

创建一个更符合逻辑的数据分组,例如:class RowData {&nbsp; &nbsp; private String country;&nbsp; &nbsp; private String gender;&nbsp; &nbsp; private double income;&nbsp; &nbsp; // constructor, getters, setters}数据包含在以下列表中:List<RowData> rowDataList = Arrays.asList(new RowData("IND", "M", 23531),&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new RowData("IND", "F", 2331), new RowData("IND", "M", 2331),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new RowData("SNG", "M", 22111), new RowData("HUD", "F", 20012));现在你可以:Map<String, Double> dataMap = rowDataList.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.groupingBy(e -> e.getCountry() + e.getGender(),&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Collectors.averagingDouble(RowData::getIncome)));

一只甜甜圈

老实说,我正在看你的第二个groupBy,我不知道发生了什么。要立即按性别 + 国家/地区分组,我最好这样:final&nbsp;Map<Pair<String,&nbsp;String>,&nbsp;List<RowData>>&nbsp;collect&nbsp;=&nbsp;rowDataStream.stream() &nbsp;&nbsp;.collect(groupingBy(rowData&nbsp;->&nbsp;Pair.of( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rowData.getCells().get(0).getValue(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rowData.getCells().get(1).getValue() &nbsp;&nbsp;)));Pair 只是任何两个值的简单容器,您可以使用 apache commons pair、vavr tuple 或创建您自己的。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java