Java groupby列并查找平均值

时间:2019-08-04 07:27:15

标签: java java-8

我以以下格式保存了要从CSV读取的数据。

accountId, recordType, amount
1, past, 40
1, past, 40
1, present, 60
2, past, 20
2, present, 10
2, present, 60

最简单的方法是处理帐户ID和recordType分组并求平均值的最简单方法。我知道可以通过结构,多个哈希图等使代码看起来难看

预期产量

accountId, recordType, amount
1, past, 40
1, present, 60
2, past, 20
2, present, 35

这是我尝试的方法,它不完整,但这就是我不满意的方法

//Map to store count of accountId to events
Map<String, Float> countHistory = new HashMap<String, Float>();
Map<String, Float> countPresent = new HashMap<String, Float>();

//Map to store count of accountId to sum of instance launched
Map<String, Float> amountPresent = new HashMap<String, Float>();
Map<String, Float> amountHistory = new HashMap<String, Float>();

for(LaunchEvent e : inputList) {
    if(e.getDataset().equalsIgnoreCase("history")) {
        countHistory.put(e.getAccountId(), amountHistory.getOrDefault(e.getAccountId(), 0.0f) + 1.0f);
        amountHistory.put(e.getAccountId(), amountHistory.getOrDefault(e.getAccountId(), 0.0f) + Float.valueOf(e.getAmount()));
    } else {
        amountPresent.put(e.getAccountId(), amountPresent.getOrDefault(e.getAccountId(), 0.0f) + 1.0f);
        amountPresent.put(e.getAccountId(), amountPresent.getOrDefault(e.getAccountId(), 0.0f) + Float.valueOf(e.getAmount()));
    }
}

2 个答案:

答案 0 :(得分:2)

关键是使用Java作为一种OO语言,您可以在其中定义类和对象。

每行是一个具有三个字段的帐户。因此,让我们定义一个具有这三个字段的类 protected void btnCreatePDF_Click(object sender, EventArgs e) { using (StringWriter sw = new StringWriter()) { using (HtmlTextWriter hw = new HtmlTextWriter(sw)) { div.RenderControl(hw); StringReader sr = new StringReader(sw.ToString()); Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 10f, 0f); PdfWriter writer = PdfWriter.GetInstance(pdfDoc, Response.OutputStream); pdfDoc.Open(); XMLWorkerHelper.GetInstance().ParseXHtml(writer, pdfDoc, sr); pdfDoc.Close(); Response.ContentType = "application/pdf"; Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Write(pdfDoc); Response.End(); } } }

您要按一个由帐户的两个字段组成的键对帐户进行分组。并且如果两个字段相等,则密钥应相等。因此,让我们定义一个类Account,该类表示该键并适当地覆盖AccountGroupingKeyequals()

对于每个键,您需要具有该键的帐户数量的平均值。因此,您需要一个hashCode()

如何创建此地图?通过使用Map<AccountGroupingKey, Double>收集器,由于您想...按密钥对帐户进行分组。然后,我们将使用groupingBy收集器将每组帐户转换为整数的平均值。

因此,最后,您需要做的是

它看起来很冗长,但是如果您省略自动生成的getter,equals和hashCode并专注于逻辑,则它实际上非常简洁易读。

averagingInt

答案 1 :(得分:0)

感谢JB Nizet。我接受了他的想法,并简化了解决方案,而无需其他课程。

frame width: 1003
table width: 1003
frame width: 1003
table width: 1003

这将产生输出

Map<String, Map<String, Double>> res = events.stream()
       .collect(Collectors.groupingBy(LaunchEvent::getAccountId,
                Collectors.groupingBy(LaunchEvent::getRecordType,
                Collectors.averagingDouble(LaunchEvent::getAmount))));