How to create a static Map of String -> Array

I need to create a static Map which maps a given String to an array of int's.

In other words, I'd like to define something like:

"fred" -> {1,2,5,8}
"dave" -> {5,6,8,10,11}
"bart" -> {7,22,10010}
... etc

Is there an easy way to do this in Java?

And if possible, I'd like to use static constants for both the String and the int values.

EDIT: To clarify what I meant by static constants for the values, and to give what I see to be the correct code, here is my first stab at the solution:

public final static String FRED_TEXT = "fred";
public final static String DAVE_TEXT = "dave";

public final static int ONE = 1;
public final static int TWO = 2;
public final static int THREE = 3;
public final static int FOUR = 4;

public final static HashMap<String, int[]> myMap = new HashMap<String, int[]>();
static {
    myMap.put(FRED_TEXT, new int[] {ONE, TWO, FOUR});
    myMap.put(DAVE_TEXT, new int[] {TWO, THREE});
}

Note, these names are not what I'd actually be using. This is just a contrived example.

Answers


You don't need to separate declaration and initialization. If you know how, it can all be done in one line!

// assumes your code declaring the constants ONE, FRED_TEXT etc is before this line
private static final Map<String, int[]> myMap = Collections.unmodifiableMap(
    new HashMap<String, int[]>() {{
        put(FRED_TEXT, new int[] {ONE, TWO, FOUR});
        put(DAVE_TEXT, new int[] {TWO, THREE});
    }});

What we have here is an anonymous class with an initialization block, which is a block of code that executes on construction after constructor, which we've used here to load the map.

This syntax/construct is sometimes erroneously called "double brace initialization" - I suppose because there's two adjacent braces - but there's actually no such thing.

The two cool things about this are:

  • it marries the declaration with the contents, and
  • because the initialization is in-line, you can also make an in-line call to Collections.unmodifiableMap(), resulting in a neat one-line declaration, initialization and conversion to unmodifiable.

If you don't need/want the map to be unmodifiable, leave out that call:

private static final Map<String, int[]> myMap = new HashMap<String, int[]>() {{
    put(FRED_TEXT, new int[] {ONE, TWO, FOUR});
    put(DAVE_TEXT, new int[] {TWO, THREE});
}};

You need to declare and initialize your static map separately.

Here is the declaration piece:

private static final Map<String,int[]> MyMap;

Here is the initialization piece:

static {
    Map<String,int[]> tmpMap = new HashMap<String,int[]>();
    tmpMap.put("fred", new int[] {1,2,5,8});
    tmpMap.put("dave", new int[] {5,6,8,10,11});
    tmpMap.put("bart", new int[] {7,22,10010});
    MyMap = Collections.unmodifiableMap(tmpMap);
}

Unfortunately, arrays are always writable in Java. You wouldn't be able to assign MyMap, but you would be able to add or remove values from other parts of your program that accesses the map.


For the sake of completeness as this is the first result in google for 'java static define map' In Java 8 you can now do this.

Collections.unmodifiableMap(Stream.of(
            new SimpleEntry<>("a", new int[]{1,2,3}),
            new SimpleEntry<>("b", new int[]{1,2,3}),
            new SimpleEntry<>("c", new int[]{1,2,3}))
            .collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue())));

This nice part with this is that we aren't creating anonymous classes anymore with the double brace syntax ({{ }})

We can then extend this with some code to clean up the pattern like this guy did here http://minborgsjavapot.blogspot.ca/2014/12/java-8-initializing-maps-in-smartest-way.html

public static <K, V> Map.Entry<K, V> entry(K key, V value) {
    return new AbstractMap.SimpleEntry<>(key, value);
}

public static <K, U> Collector<Map.Entry<K, U>, ?, Map<K, U>> entriesToMap() {
    return Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue());
}

public static <K, U> Collector<Map.Entry<K, U>, ?, ConcurrentMap<K, U>> entriesToConcurrentMap() {
    return Collectors.toConcurrentMap((e) -> e.getKey(), (e) -> e.getValue());
}

final result

Collections.unmodifiableMap(Stream.of(
            entry("a", new int[]{1,2,3}),
            entry("b", new int[]{1,2,3}),
            entry("c", new int[]{1,2,3}))
            .collect(entriesToMap()));

which would give us a Concurrent Unmodifiable Map.


static Map<String, int[]> map = new HashMap<>();

The map is static, you can access it without creating an instance of the class it's defined in. I don't know what you mean with having the keys and values static as well, because it makes no sense to me.


public class ExampleClass {
    public final static HashMap consts = new HashMap();
    static
    {
        constants.put("A", "The Letter A");
        constants.put("B", "The Letter B");
        constants.put("C", "The Letter C");
    }
    /* Rest of your class that needs to know the consts */
}

Need Your Help

PHP switch statement inside another switch statement

php switch-statement

I have this situation where I have to check two GET variables. After checking the first one in one switch statement inside the statement, the second variable has to be checked in the second switch