Java 使用集合框架进行数据聚合
在了解什么是数据聚合之前,让我们先看看这个问题。给你一个喜欢吃糖果的人每天消费不同类型的糖果。输入的数据如下。
输入表
汇总前的数据
希望的输出表
汇总后的数据
以上是汇总后的数据。现在我们来了解一下什么是数据聚合?
什么是数据聚合?
让我们通过一个例子来理解它。例如,在输入表中,我们得到了每天不同种类的糖果的消费数量。例如,2022年8月28日,志愿者只消费了2种糖果,即KitKat和Hershey’s。而在2022年8月29日,该志愿者消费了4种糖果,分别是KitKat、Skittles、Alpen Liebe和Cadbury。现在,我们也得到了消费金额。例如,2022年8月29日,吃得最多的糖果是吉百利。而2022年8月28日吃的最多的糖果是KitKat。然而,看了输入表,我们无法直接回答以下问题。哪种糖果是每天最受欢迎的(甚至哪种糖果在总体上受欢迎)?
现在,看着上面的输入表,我们似乎可以通过立即查看数据的匹配日期来回答这个问题。但是想象一下,我们进行了一个月或一个季度的调查,我们现在又引入了100个品牌的糖果供志愿者选择和食用。数据的规模会迅速增长,以至于仅仅通过查看表格就能回答这个问题几乎是不可能的。甚至还有另一种可能,即数据是分散的,以至于为某一特定日期收集的数据并不像上面的输入表那样连续显示。在这种情况下,直接看原始数据并回答会变得更加复杂。
现在,为了有效地回答这些统计问题,我们需要组织我们的数据。我们需要对数据进行分类,以便通过查看我们转换后的数据,我们可以立即回答这个问题,即:哪种糖果每天更受欢迎?例如,通过查看汇总后的数据,我们可以说,在8月28日,KitKat吃得更多,而在8月29日,仅通过查看每个日期下的列,就可以知道吉百利吃得更多。不仅如此,我们现在还可以回答以下问题。
1.在哪一天,某一种糖果被吃得更多?(通过查看该糖果的行数)
2.哪种糖果在总体上是受欢迎的?(通过查看最后一栏 “总数”)。
3.哪一天见证了最多的糖果消费?(通过查看最后一行的 “总数”)
比如说。
- Alpenliebe在8月27日和8月29日被吃得更多。
- 另一方面,Kitkat是总体受欢迎的糖果。
- 8月29日被证明是糖果消费最多的一天。也许,我们可以宣布这是“糖果日”。
因此,我们正在体验汇总数据的好处。这是一种为了分析数据而总结我们所掌握的数据的技术,使原始数据更有意义。我们现在处于一个更有效的位置来回答上述问题。
问题陈述
我们需要将给定的特定日期的糖果消费的输入表转化为一个汇总表,其中对每一种糖果收集的数据应汇总为一天的数值。(参照上面的输出表)。以下是上述问题的代码。
import java.util.*;
class CandyConsumption {
String date;
String candy;
int consumption;
CandyConsumption(String date, String candy, int consumption){
this.date = date;
this.candy = candy;
this.consumption = consumption;
}
public String toString(){
StringBuffer str = new StringBuffer();
str.append( date );
str.append( "\t\t\t\t" );
str.append( String.valueOf( candy ) );
str.append( "\t\t\t\t" );
str.append( String.format("%20s", String.valueOf( consumption ) ));
return str.toString() ;
}
public static void main(String[] args){
CandyConsumption[] cc = new CandyConsumption[9];
cc[0] = new CandyConsumption("27-08-2022", "skittles", 20);
cc[1] = new CandyConsumption("27-08-2022", "Kitkat", 10);
cc[2] = new CandyConsumption("27-08-2022", "Alpenliebe", 20);
cc[3] = new CandyConsumption("28-08-2022", "Kitkat", 30);
cc[4] = new CandyConsumption("28-08-2022", "Hershey's", 25);
cc[5] = new CandyConsumption("29-08-2022", "Kitkat", 30);
cc[6] = new CandyConsumption("29-08-2022", "skittles", 15);
cc[7] = new CandyConsumption("29-08-2022", "Alpenliebe", 20);
cc[8] = new CandyConsumption("29-08-2022", "Cadbury", 45);
// Before Aggregation
System.out.println("Date\t\t\t\t\tCandy\t\t\t\tConsumption");
for( int i = 0 ; i < cc.length ; i++ ) {
System.out.println(cc[i]) ;
}
System.out.println();
System.out.println();
System.out.println("After Aggregation");
System.out.println();
// After aggregation
aggregate(cc);
}
public static void aggregate(CandyConsumption[] cc){
// Key => Candy Column (a/c to output table) |
// Value = Another HashMap which maps each date
// to the amount of candies consumed on that date
HashMap<String, HashMap<String, Integer>> map = new HashMap<>();
// An arraylist to store unique dates
ArrayList<String> dates = new ArrayList<>();
// HashMap to calculate total consumption datewise
// Key => Date | Value => Total number of
// candies consumed on that Date
HashMap<String, Integer> consumptionDatewise = new HashMap<>();
// HashMap to calculate total consumption candywise
// Key => Candy | Value => Total number of candies
// consumed of that Candy type
HashMap<String, Integer> consumptionCandywise = new HashMap<>();
// Populate map HashMap
for(int i=0;i<cc.length;i++){
String date = cc[i].date;
String candy = cc[i].candy;
int consumption = cc[i].consumption;
if(!map.containsKey(candy)){
map.put(candy, new HashMap<>());
}
map.get(candy).put(date, consumption);
// Let's also populate the dates
// arraylist simultaneously
if(!dates.contains(date)){
dates.add(date);
}
// Let's also populate the
// consumptionDatewise hashmap
if(!consumptionDatewise.containsKey(date)){
consumptionDatewise.put(date, 0);
}
consumptionDatewise.put(date, consumptionDatewise.getOrDefault(date, 0) + consumption);
}
// We have calculated total consumption datewise.
// Let's now calculate the total consumption
// of each candy
for(String candy : map.keySet()){
HashMap<String, Integer> candyVal = map.get(candy);
int total = 0;
for(String date : candyVal.keySet()){
total += candyVal.get(date);
}
consumptionCandywise.put(candy, total);
}
// We are done with all the necessary pre-processing.
// Let's start printing.
// Let's print the Header Line first
System.out.print(String.format("%-15s", "Candy/Date"));
for(String date : dates){
System.out.print(date + "\t");
}
System.out.println("Total");
// Printing the rest of the table
for(String candy : map.keySet()){
// System.out.printf("%-4s", candy);
System.out.print(String.format("%-15s" , candy));
HashMap<String, Integer> candyVal = map.get(candy);
for(int I = 0; I < dates.size(); i++){
if(!candyVal.containsKey(dates.get(i)))
System.out.print("0" + "\t\t");
else
System.out.print(candyVal.get(dates.get(i)) + "\t\t");
}
// Finally printing the total candywise
System.out.println(consumptionCandywise.get(candy));
}
// Printing the Total consumption datewise :- Last Line
System.out.print(String.format("%-15s", "Total"));
int total = 0;
for(int i=0;i<dates.size();i++){
int candiesOnDate = consumptionDatewise.get(dates.get(i));
total += candiesOnDate;
System.out.print(candiesOnDate + "\t\t");
}
System.out.println(total);
}
}
输出:
Date Candy Consumption
27-08-2022 skittles 20
27-08-2022 Kitkat 10
27-08-2022 Alpenliebe 20
28-08-2022 Kitkat 30
28-08-2022 Hershey's 25
29-08-2022 Kitkat 30
29-08-2022 skittles 15
29-08-2022 Alpenliebe 20
29-08-2022 Cadbury 45
After Aggregation
Candy/Date 27-08-2022 28-08-2022 29-08-2022 Total
Kitkat 10 30 30 70
Cadbury 0 0 45 45
Alpenliebe 20 0 20 40
Hershey's 0 25 0 25
skittles 20 0 15 35
Total 50 55 110 215