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
3 Answers
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.

- 76,138
- 12
- 138
- 194
-
1Your insensitivity to the calendars of non-European cultures is appalling! – erickson Jun 14 '13 at 19:13
-
So this is a arraylist of arraylist? How does this store month say Jan and Have data against it? and I could keep adding the data agaisnt jan if need be, New to Java!!!! – Matt R Jun 14 '13 at 19:26
-
I was thinking more like List or Map of some kind that has the month say Jan and has data that keeps on adding into it. So month here would be the key and data that gets added to that specific month be the value. Can we do that? – Matt R Jun 14 '13 at 19:28
-
Why not use integers `0` to `11` as index? It's faster. Repeated string hashing is a slow way of achieving the same. – Has QUIT--Anony-Mousse Jun 14 '13 at 19:49
-
Yep, I am using 0 to 11. Thanks – Matt R Jun 14 '13 at 20:15
-
to retrieve the values from the ArrayList do I use something like this – Matt R Jun 14 '13 at 20:17
-
This is the problem now. I do the initialize, then go into a loop and add stuff there into the list. But everytime I try to add, the value in the list becomes zero due to initialization. I am basically unable to pile on data, on already existing value, how do I solve that – Matt R Jun 20 '13 at 19:59
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.

- 1,265
- 10
- 18
-
-
@erickson was not aware of them. Just went through the javadoc. Compactness and natural ordering seemed to be something different. Any reason you specifically suggested for them? – Dhrubajyoti Gogoi Jun 14 '13 at 21:11
-
The map will iterate in the `enum` order. So it's an easy way to get the output you are likely to want. They also perform better and provide extra type safety. – erickson Jun 14 '13 at 21:25
-
FYI, Java 8 and later has a built-in [`Month`](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) enum. – Basil Bourque Apr 19 '18 at 04:39
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 );
}
}

- 303,325
- 100
- 852
- 1,154