Alexey Romanov
Alexey Romanov

Reputation: 170735

Compact way to create Guava Multimaps?

If I want to create a new Multimap with simple defaults, I curently need to do something like:

private final Multimap<Key, Value> providersToClasses = Multimaps
        .newListMultimap(
                new HashMap<Key, Collection<Value>>(),
                new Supplier<List<Value>>() {
                    @Override
                    public List<Value> get() {
                        return Lists.newArrayList();
                    }
                });

...because Java can't infer the correct types if Maps.newHashMap is used for the backing map. Of course, this can be refactored into a separate method, but is there already a way to write it more concisely?

Upvotes: 46

Views: 52221

Answers (6)

Pyves
Pyves

Reputation: 6483

The Guava documentation states that the create method advocated by some other answers "will soon be deprecated" in favour of the different forms presented below, and should therefore be avoided.

From Guava 21.0 onwards, the recommended way of creating a Multimap object where values are stored in ArrayList collections is the following:

MultimapBuilder.hashKeys().arrayListValues().build();

You can also use parameters if you want to specify the expected number of keys in your map and the expected number of values per key:

MultimapBuilder.hashKeys(expectedKeys).arrayListValues(expectedValuesPerKey).build();

Finally, you can create a new Multimap from an existing one using this construct:

MultimapBuilder.hashKeys().arrayListValues().build(multimap);

If you want to use data structures other than ArrayLists in your Multimap, you can replace the call to arrayListValues() by a number of other ones, listed here.

Upvotes: 15

Here is compact solution:

Multimap<Integer, String> multi = HashMultimap.create();

Upvotes: 6

Lii
Lii

Reputation: 12112

In Java 8 this is much nicer, for all kinds of multimaps. This is for two reasons:

It looks like this:

Multimap<Key, Value> providersToClasses =
    Multimaps.newListMultimap(new HashMap<>(), ArrayList::new);

Upvotes: 4

Sam Berry
Sam Berry

Reputation: 7844

I run into this problem when writing clients and building up maps of query params. A nice succinct pattern I like for constructing multi-maps is to use ImmutableMultiMap#builder

Multimap<String, String> queryParams = 
  ImmutableMultimap.<String, String>builder()
    .put("key-1", "value-1")
    .put("key-1", "value-2")
    .build();

Upvotes: 27

Daniel Teply
Daniel Teply

Reputation: 1974

Why aren't you using ArrayListMultimap.create() for such a simple case? It's the default way to create the simple HashMap/ArrayList that is probably the most common used multimap.

Upvotes: 62

Frank Pavageau
Frank Pavageau

Reputation: 11705

To answer the original type inference problem, though, you can also specify the generic types on a static method using Maps.<Key, Collection<Value>>newHashMap(), but it's certainly not more concise than new HashMap<Key, Collection<Value>>() (it may be more consistent).

Upvotes: 2

Related Questions