Is this a correct way to use Nested groupby in java8?

cafebabe1991 :

I have the following objects.

class RowData
{
  private List<RowCell> cells;
}

class RowCell
{
  private String headerName;
  private String value;
}

I have loaded the following CSV into these objects.

Country,Gender,Income
IND,M,23531
IND,F,2331
IND,M,2311
SNG,M,22111
HYD,F,20012

What I need to do ?

Find average income grouped by Country and gender.

What have I done so far ?

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

Questions

  1. Is this the right way to do it ?
  2. It seems overly complex. Can you suggest a better way to do it ?
Michael :

First, you probably should load your data into meaningful DTOs / POJOs:

class Row {
    String country;
    String gender;
    int income;
    // Getters etc.
}

Then, given a List<Row>, you can simply do this:

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)
)

And for the structure you have given (list of RowData with 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()))
)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=127590&siteId=1