【发布时间】:2019-08-28 10:08:51
【问题描述】:
这是我的“revenue_data.csv”文件:
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
而我读取文件的案例类是:
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;
}
}
我可以通过以下方式按 ReportDate, sum(revenue) 读取文件和组:
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)));
}
}
我的问题是如何在 Java 8 中按 ReportDate、count(clientCode) 和 sum(revenue) 进行分组,具体来说:
- 使用什么集合代替地图
- 在这种情况下如何进行分组和收集(通常用于 2 个以上的分组)
我正在尝试:
//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()))));
但是在 RevenueRecorder::getReportDate 下获取 Intellij red-squiggle 并带有悬停消息“不能从静态上下文引用非静态方法”。
谢谢
编辑 为澄清起见,这是我试图获取的相应 SQL 查询:
select
reportDate, count(distinct(clientCode)), sum(revenue)
from
revenue_data_table
group by
reportDate
【问题讨论】:
-
可能更容易创建自己的聚合类并收集到其中。
-
C1、C2和C3等客户端代码如何映射到Integer?多个客户端代码应该如何组合成一个Pair? -
Map<LocalDate, Pair<Integer, Integer>> pairedReportDateMRR = revenueRecords.stream() .collect(Collectors.toMap(RevenueRecorder::getReportDate, v -> new Pair<>(1, v.getRevenue()), (p1, p2) -> new Pair<>(p1.getKey() + p2.getKey(), p1.getValue() + p2.getValue())));我没有测试过。 -
当您按客户端键分组时,您会得到包含客户端键的结果,即从客户端键到值的
Map映射,而不是整数。 -
@Hadi:你的解决方案有效,只需要用具体的实现来改变抽象的 Pair(),谢谢;
标签: java java-8 java-stream grouping