Matt R
Matt R

Reputation: 21

How do I add data for a specific months in java

Here is the scenario, I have monthly data that I have to insert into a data structure and then retrieve it. So say Data a goes into Jan month, Data b goes into June month, and Data c goes into Jan month. Once the inserts are done, then I add all the data for a given month and retrieve it. So for Jan it will be a+b, for Feb it could be d+e+f and so forth. How can I accomplish this in Java? Kindly help. Thanks Matt

Upvotes: 1

Views: 761

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 339362

Month enum, EnumMap, and functional streams

The modern approach uses java.time classes, a Map, and perhaps even the functional side of Java with Java Streams.

The Month enum defines a dozen objects, one for each month of the year. Use EnumMap as your Map, because it is highly optimized for enums as your keys.

Map < Month, List < Integer > > map = new EnumMap( Month.class );

Put an empty ArrayList<Integer> as the value for each key. The ArrayList can only hold objects (Integer), not primitives (int). Fortunately, auto-boxing converts back-and-forth for us automatically.

// Pre-populate.
for ( Month m : EnumSet.allOf( Month.class ) ) {
    map.put( m , new ArrayList <>() );
}

// Add some data.
List < Integer > list;

list = map.get( Month.FEBRUARY );
list.addAll( List.of( 1 , 2 , 3 ) );

list = map.get( Month.MAY );
list.addAll( List.of( 44 , 22 ) );

Looping

Loop through each key, getting the list for each. If the list is empty, skip it (or you could report zero). If not empty, loop to add the values of the elements in the list. Again, auto-boxing to the rescue for object↔primitive conversion.

For reporting, we ask the Month enum object to generate a localized name for that month in English, French, whatever.

// Report
for ( Month m : map.keySet() ) {
    list = map.get( m );
    if ( ! list.isEmpty() ) {
        int sum = 0;
        for ( Integer integer : list ) {
            sum = ( sum + integer );
        }
        System.out.println( m.getDisplayName( TextStyle.FULL , Locale.US ) + " = " + sum );
    }
}

February = 6

May = 66

Streams

Instead of looping, we can use the functional approach in Java, using Java Streams to calculate an aggregate. Discussed on other Questions, here and here and here.

// Report
for ( Month m : map.keySet() ) {
    list = map.get( m );
    if ( ! list.isEmpty() ) {
        int sum = list.stream().mapToInt( Integer :: intValue ).sum();
        System.out.println( m.getDisplayName( TextStyle.FULL , Locale.US ) + " = " + sum );
    }
}

Upvotes: 0

Dhrubajyoti Gogoi
Dhrubajyoti Gogoi

Reputation: 1340

If you are asking for a Map you may try something like this:

// Month enum.
enum Month {JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC}

// Map for storing months against values.
Map<Month, Double> monthMap = new HashMap<Month, Double>();

// Initialize month map with 0.0 value. You may implement it differently.
void initMonthMap() {
    for (Month m : Month.values())  {
        monthMap.put(m, 0.0);
    }
}

// Function to add values to a month.
void addValue(Month m, Double v)    {
    monthMap.put(m, monthMap.get(m) + v); 
}

// Eg. Adding values to a month.
addValue(Month.JAN, 12.0);

Later you can fetch the summed up values for any/every month.

Upvotes: 0

Has QUIT--Anony-Mousse
Has QUIT--Anony-Mousse

Reputation: 77474

How about using an Array/ArrayList with 12 entries?

ArrayList<ArrayList<Double>> data = new ArrayList<>(12);

You need to initialize it:

for (int i = 0; i < 12) {
    data.add(new ArrayList<Double>());
}

You then can add data by:

data.get(month - 1).add(123.);

Note that indexes start with 0.

Warning: Collections of primitive objects don't scale very well. They need much more memory than necessary. If you have lots of data, using GNU Trove may pay off quickly.

However, if you just want to sum them, how about doing this:

 double[] sums = new double[12];

 sums[month - 1] += value;

Just compute the 12 sums right away.

Upvotes: 3

Related Questions