Агрегация данных в Java с использованием Collections Framework

Опубликовано: 8 Января, 2023

Давайте рассмотрим проблему, прежде чем понять, что такое агрегация данных. Вам дается ежедневное потребление различных видов конфет сладкоежкой. Вход дается следующим образом.

Входная таблица:

Желаемая выходная таблица:

Выше приведены сводные данные. Теперь давайте разберемся, что такое агрегация данных?

Что такое агрегация данных?

Давайте разберемся на примере. Например, во входной таблице нам дано количество потребления различных видов конфет каждый день. Например, 28 августа 2022 года волонтер съел только 2 вида конфет: KitKat и Hershey's. Принимая во внимание, что 29 августа 2022 года волонтер съел 4 вида конфет: KitKat, Skittles, Alpen Liebe и Cadbury. Теперь нам также дается количество потребления. Например, самая съеденная конфета 29 августа 2022 года — это Cadbury. Принимая во внимание, что самой съеденной конфетой 28 августа 2022 года является KitKat. Однако, глядя на входную таблицу, мы не можем прямо ответить на следующий вопрос: какие конфеты самые популярные каждый день (или даже какие конфеты популярны в целом)?

Теперь, похоже, глядя на приведенную выше входную таблицу, мы можем ответить на вопрос, немедленно просматривая данные для совпадения дат. Но представьте, мы проводим опрос на месяц или квартал и теперь представляем еще 100 марок конфет, чтобы волонтер мог выбрать и съесть. Объем данных будет расти так быстро, что ответить на вопрос, просто взглянув на таблицу, будет практически невозможно. Существует даже другая возможность, когда данные разбросаны так, что данные, собранные за определенную дату, не отображаются последовательно, как показано в таблице ввода выше. В этом случае было бы еще сложнее напрямую смотреть на необработанные данные и отвечать.

Теперь, чтобы эффективно ответить на такие статистические вопросы, нам нужно организовать наши данные. Нам нужно классифицировать данные таким образом, чтобы, глядя на наши преобразованные данные, мы могли сразу же ответить на вопрос: какие конфеты более популярны каждый день? Например, глядя на данные после агрегирования, мы можем сказать, что 28 августа больше съедено KitKat, а 29 августа больше съедено Cadbury, просто взглянув на столбец под каждой датой. Не только это, но теперь мы также можем ответить на следующие вопросы:

  1. В какой день тот или иной вид конфет был съеден больше? (Глядя на ряд этих конфет)
  2. Какие конфеты популярны в целом? (Посмотрев на последнюю колонку «Всего»).
  3. В какой день было больше всего съедено конфет? (Глядя на последнюю строку «Всего»)

Например,

  • Альпенлибе съели больше 27 и 29 августа.
  • Kitkat, с другой стороны, является самой популярной конфетой.
  • 29 августа оказалось днем, когда было съедено больше всего конфет. Может быть, мы можем объявить его «Днем конфет» .

Таким образом, мы испытываем преимущества агрегирования данных. Это метод обобщения данных, которые у нас есть, с целью их анализа, что делает необработанные данные более значимыми. Теперь мы находимся в более эффективном положении, чтобы ответить на вышеуказанные вопросы.

Постановка задачи

Нам необходимо преобразовать заданную входную таблицу потребления конфет в конкретную дату в агрегированную таблицу, в которой данные, собранные для каждой конфеты, должны быть объединены в значение за день. (См. выходную таблицу выше). Ниже приведен код для вышеуказанной проблемы:

Java




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( " " );
        str.append( String.valueOf( candy ) );
        str.append( " " );
        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 Candy Consumption");
        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 + " ");
        }
        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" + " ");
                else 
                    System.out.print(candyVal.get(dates.get(i)) + " ");
            }
  
            // 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 + " ");
        }
        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