Search code examples
javaarraysgenericsdictionaryinstantiation

How does one instantiate an array of maps in Java?


I can declare an array of maps using generics to specify the map type:

private Map<String, Integer>[] myMaps;

However, I can't figure out how to instantiate it properly:

myMaps = new HashMap<String, Integer>[count]; // gives "generic array creation" error
myMaps = new HashMap[count]; // gives an "unchecked or unsafe operation" warning
myMaps = (Map<String, Integer>[])new HashMap[count]; // also gives warning

How can I instantiate this array of maps without getting a compiler error or warning?

Update:

Thank you all for your replies. I ended up going with the List suggestion.


Solution

  • You can't safely create a generic array. Effective Java 2nd Edition goes into the details in the chapter on Generics. Start at the last paragraph of page 119:

    Why is it illegal to create a generic array? Because it isn’t typesafe. If it were legal, casts generated by the compiler in an otherwise correct program could fail at runtime with a ClassCastException. This would violate the fundamental guarantee provided by the generic type system.

    To make this more concrete, consider the following code fragment:

    // Why generic array creation is illegal - won't compile!
    List<String>[] stringLists = new List<String>[1]; // (1)
    List<Integer> intList = Arrays.asList(42); // (2)
    Object[] objects = stringLists; // (3)
    objects[0] = intList; // (4)
    String s = stringLists[0].get(0); // (5)
    

    Let’s pretend that line 1, which creates a generic array, is legal. Line 2 creates and initializes a List<Integer> containing a single element. Line 3 stores the List<String> array into an Object array variable, which is legal because arrays are covariant. Line 4 stores the List<Integer> into the sole element of the Object array, which succeeds because generics are implemented by erasure: the runtime type of a List<Integer> instance is simply List, and the runtime type of a List<String>[] instance is List[], so this assignment doesn’t generate an ArrayStoreException. Now we’re in trouble. We’ve stored a List<Integer> instance into an array that is declared to hold only List<String> instances. In line 5, we retrieve the sole element from the sole list in this array. The compiler automatically casts the retrieved element to String, but it’s an Integer, so we get a ClassCastException at runtime. In order to prevent this from happening, line 1 (which creates a generic array) generates a compile-time error.

    Because arrays and generics don't combine well (as well as other reasons), it's generally better to use Collection objects (in particular List objects) rather than arrays.