ArrayListMultimap#asMap returns Collection instead of ArrayList

1,197 views
Skip to first unread message

els

unread,
Apr 13, 2012, 7:11:11 AM4/13/12
to guava-...@googlegroups.com

Hi there

I was doing some work with an own Multimap. The big difference is when I call asMap on the ArrayListMultimap I get a "Map<K, ArrayList<V>>" instead of "Multimap<K, Collection<V>>". I've done it like this:
public interface Multimap<K, V, L extends Collection<V>> {
...
Map<K, L> asMap();
...
}
So the ListMultimap would look like this:
public interface ListMultimap<K, V, L extends List<V>> extends Multimap<K, V, L> {}

And the ArrayListMultimap would show:
public class ArrayListMultimap<K, V> implements ListMultimap<K, V, ArrayList<V>> {
...
   public Map<K, ArrayList<V>> asMap() { ....  }
...
}

Is there a special reason not to do it so?

Cheers Adrian

Louis Wasserman

unread,
Apr 13, 2012, 10:07:20 AM4/13/12
to els, guava-...@googlegroups.com
First, it would be absolutely impossible to return a Map<K, ArrayList<V>>; the returned lists are wrappers over backing ArrayLists, not ArrayLists themselves.  Furthermore, for reasons of generic type compatibility with Multimap, it is impossible to specialize the type of the returned map.  http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ListMultimap.html#asMap() implies that it is legal to cast the returned Map to Map<K, List<V>>, which you should feel free to do.

Chris Povirk

unread,
Apr 13, 2012, 10:30:27 AM4/13/12
to Louis Wasserman, els, guava-...@googlegroups.com
> First, it would be absolutely impossible to return a Map<K, ArrayList<V>>;
> the returned lists are wrappers over backing ArrayLists, not ArrayLists
> themselves.

A major reason for this is that we want to be able to remove the
backing lists from our internal map when they become empty but still
allow users to add elements to the wrapper to "resurrect" the key. If
we use a plain ArrayList, either we have to keep it in our internal
map forever, or we have to declare that, once the final element is
removed, it is no longer possible to modify the Multimap through the
list.

We did have a Multimap implementation internally that used ArrayList
(or any other type of your choice) for value collections. From the
two above options, we chose to never remove empty collections from our
backing map. This is probably fine for a lot of users. However, the
implementation never caught on. In part that's because there was no
singular use case that it served, so it was hard to know how to
promote it.

Colin Decker

unread,
Apr 13, 2012, 10:42:29 AM4/13/12
to Chris Povirk, Louis Wasserman, els, guava-...@googlegroups.com
In addition to all of this, adding an extra type parameter to the Multimap interface seems highly undesirable given the little value it could provide. It would be pretty unpleasant to use Multimaps if you had to deal with Multimap<K, V, ? extends Collection<V>> or some such all over the place in your code. Just specifying the key and value types like with Map is simple and avoids putting too much emphasis on the implementation that's used for storing values.

-- 
Colin


Joe Kearney

unread,
Apr 18, 2012, 5:30:21 AM4/18/12
to Colin Decker, Chris Povirk, Louis Wasserman, els, guava-...@googlegroups.com
Agreed that having to specify the third type parameter all the time would be annoying. But I dispute that there's little value in having something there. It's annoying having a ListMultimap<K, V> and having to cast the values collections from Collection<V> to List<V>. A lot of the time that I use an XxxMultimap it's because I need access to the values as an Xxx.

It would be nice to introduce some super-interface GenericMultimap<K, V, C extends Collection<V>>, where Multimap<K, V> extends GenericMultimap<K, V, Collection<V>>. This would allow ListMultimap.values() to return a List without the third type parameter on MultiMap or ListMultimap. Though I'm not sure that it's possible to maintain the relationship (XxxMultimap extends Multimap) in that case, which would just present a new problem. Has anyone looked at this kind of idea to retrofit the third type parameter?

Joe

Kevin Bourrillion

unread,
Apr 18, 2012, 5:34:24 AM4/18/12
to Joe Kearney, Colin Decker, Chris Povirk, Louis Wasserman, els, guava-...@googlegroups.com
I'm pretty sure that as long as ListMultimap extends Multimap we can't get the behavior you want.  Sad but true.

And for all the years we had the <K, V, C> thing internally, we never got anyone to actually use it.  It's just too obscure; too hard for users who would actually benefit from it to actually know it exists.

Kevin Bourrillion @ Google
Java Core Libraries Team
http://guava-libraries.googlecode.com

Reply all
Reply to author
Forward
0 new messages