我有以下对象。
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()))));
问题
答案 0 :(得分:2)
老实说,我正在看您的第二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()
)));
对只是任意两个值的简单容器,您可以使用apache commons对,vavr tuple或创建自己的对。
答案 1 :(得分:2)
首先,您可能应该将数据加载到有意义的DTO / POJO中:
class Row {
String country;
String gender;
int income;
// Getters etc.
}
然后,给定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
和RowCell
的列表):
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()))
)
答案 2 :(得分:2)
创建更具逻辑性的数据分组,例如:
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)));