170

Guava offers a nice shortcut for initializing a map. However I get the following compiler error (Eclipse Indigo) when my map initializes to nine entries.

The method of(K, V, K, V, K, V, K, V, K, V) in the type ImmutableMap is not applicable for the arguments (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String)

ImmutableMap<String,String> myMap = ImmutableMap.of(
        "key1", "value1", 
        "key2", "value2", 
        "key3", "value3", 
        "key4", "value4", 
        "key5", "value5", 
        "key6", "value6", 
        "key7", "value7", 
        "key8", "value8", 
        "key9", "value9"
        );

The message appears to say that

An ImmutableMap has a maximum size of four pairs of key,value.

Obviously, this cannot be the case but I can't figure out what to do to increase the size of my initializer.

Can someone tell me what is missing?

user903724
  • 2,956
  • 4
  • 24
  • 27

3 Answers3

314

Notice that your error message only contains five K, V pairs, 10 arguments total. This is by design; the ImmutableMap class provides six different of() methods, accepting between zero and five key-value pairings. There is not an of(...) overload accepting a varags parameter because K and V can be different types.

You want an ImmutableMap.Builder:

ImmutableMap<String,String> myMap = ImmutableMap.<String, String>builder()
    .put("key1", "value1") 
    .put("key2", "value2") 
    .put("key3", "value3") 
    .put("key4", "value4") 
    .put("key5", "value5") 
    .put("key6", "value6") 
    .put("key7", "value7") 
    .put("key8", "value8") 
    .put("key9", "value9")
    .build();
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Thanks for the quick answers. I decided to try Guava because I did not want to have to type all the 'puts' required by a standard map initializer. So much for that idea! – user903724 Feb 28 '12 at 20:59
  • 9
    @user903724: The main reason for using Guava here is the strong immutability, IMO. – Jon Skeet Feb 28 '12 at 21:09
  • 2
    That, or the slightly reduced memory consumption -- and the builder syntax is pretty fluent, as things go. – Louis Wasserman Feb 28 '12 at 21:19
  • 2
    well, you may have multiple puts still, but they are now using fluent API, so no need to repeat `myMap` for each `.put` – Kevin Welker Feb 28 '12 at 22:25
  • 24
    Notice also how Jon's example code could be a `public static final` and it still works, no need for a helper method or `static{}` initializer! – Kevin Bourrillion Feb 29 '12 at 03:57
70

if the map is short you can do:

ImmutableMap.of(key, value, key2, value2); // ...up to five k-v pairs

If it is longer then:

ImmutableMap.builder()
   .put(key, value)
   .put(key2, value2)
   // ...
   .build();
Grzegorz Rożniecki
  • 27,415
  • 11
  • 90
  • 112
Nathan Feger
  • 19,122
  • 11
  • 62
  • 71
1

If you want a balance between capability and readability, you may combine both approaches:

ImmutableMap<String,String> myMap = ImmutableMap.<String, String>builder()
    .putAll(ImmutableMap.of(
        "key1", "value1", 
        "key2", "value2", 
        "key3", "value3", 
        "key4", "value4"));
    .putAll(ImmutableMap.of(
        "key5", "value5", 
        "key6", "value6", 
        "key7", "value7", 
        "key8", "value8", 
        "key9", "value9"));
    .build();

Whether or not this is a good idea, is something open to discussion.

Haroldo_OK
  • 6,612
  • 3
  • 43
  • 80