More than 2 groupingBy operations in Java 8

shanlodh :

This is my "revenue_data.csv" file:

Client  ReportDate  Revenue
C1      2019-1-7    12
C2      2019-1-7    34
C1      2019-1-16   56
C2      2019-1-16   78
C3      2019-1-16   90

And my case class to read the file is:

package com.source.code;

import java.time.LocalDate;

public class RevenueRecorder {

    private String clientCode;
    private LocalDate reportDate;
    private int revenue;


    public RevenueRecorder(String clientCode, LocalDate reportDate, int revenue) {
        this.clientCode = clientCode;
        this.reportDate = reportDate;
        this.revenue = revenue;
    }

    public String getClientCode() {
        return clientCode;
    }

    public LocalDate getReportDate() {
        return reportDate;
    }

    public int getRevenue() {
        return revenue;
    }
}

I can read the file and group by ReportDate, sum(revenue) in the following manner:

import com.source.code.RevenueRecorder;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.summingInt;

public class RevenueRecorderMain {

    public static void main(String[] args) throws IOException {

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-M-d");
        List<RevenueRecorder> revenueRecords = new ArrayList<>();

        Path path = FileSystems.getDefault().getPath("src", "main", "resources",
                "data", "revenue_data.csv");

        Files.lines(path)
                .skip(1)
                .map(s -> s.split(","))
                .forEach(s ->
                {
                    String clientCode = s[0];
                    LocalDate reportDate = LocalDate.parse(s[1], formatter);
                    int revenue = Integer.parseInt(s[2]);

                    revenueRecords.add(new RevenueRecorder(clientCode, reportDate, revenue));

                });

        Map<LocalDate, Integer> reportDateRev = revenueRecords.stream()
                .collect(groupingBy(RevenueRecorder::getReportDate,
                        summingInt(RevenueRecorder::getRevenue)));
    }
}

My question is how can I group by ReportDate, count(clientCode) and sum(revenue) in Java 8, specifically:

  • what collection to use instead of the Map
  • how to groupby and collect in this case (and generally for more than 2 groupingBy's)

I'm trying:

//import org.apache.commons.lang3.tuple.ImmutablePair;
//import org.apache.commons.lang3.tuple.Pair;

        Map<LocalDate, Pair<Integer, Integer>> pairedReportDateRev = revenueRecords.stream()
                .collect(groupingBy(RevenueRecorder::getReportDate,
                        new ImmutablePair(summingInt(RevenueRecorder::getRevenue),
                        groupingBy(RevenueRecorder::getClientCode, Collectors.counting()))));

But getting the Intellij red-squiggle underneath RevenueRecorder::getReportDate with the hover-message 'Non-static method cannot be referenced from a static context'.

Thanks

EDIT For clarification, here's the corresponding SQL query that I'm trying to get at:

select 
    reportDate, count(distinct(clientCode)), sum(revenue)
from
    revenue_data_table
group by
    reportDate
zhouxin :

Although your trying has not been successful, but I think is what you most want to express. So I just follow your code and fix it. Try this one!

Map<LocalDate, ImmutablePair<Integer, Map<String, Long>>> map = revenueRecords.stream()
            .collect(groupingBy(RevenueRecorder::getReportDate,
                    collectingAndThen(toList(), list -> new ImmutablePair(list.stream().collect(summingInt(RevenueRecorder::getRevenue)),
                                                                          list.stream().collect(groupingBy(RevenueRecorder::getClientCode, Collectors.counting()))))));

And I borrowed some sample data code from @Lyashko Kirill to test my code, the result is below enter image description here

This's my own idea, I hope I can help you. ╰( ̄▽ ̄)╭

Guess you like

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