Java Generics overlay <String ,? extends List <String>>

Is there a way to make the following implementation in a safe way?

public void myMethod( Map<String, ? extends List<String>> map ) { map.put("foo", Collections.singletonList("bar"); } 

The above implementation does not work. To compile the map.put() method map.put() , Map<String, ? super List<String>> Map<String, ? super List<String>> . But myMethod will not accept any List subtype in this form. So, should I use Map<String, ? extends List<String>> Map<String, ? extends List<String>> . How can I solve this problem in a safe way?

+6
java collections list generics map
source share
4 answers
 public void myMethod( Map<String, List<String>> map ) { map.put("foo", Collections.singletonList("bar") ); } 

You cannot put a List (the returned type of Collections.singletonList() on a Map of ? extends List , since the actual type can be any implementation of List . For example, it is unsafe to put a generic List in Map<String,LinkedList> , since the List may not be LinkedList . However, we can easily put a LinkedList in the Map of <String,List> .

I think you already thought about your generics. You do not need to use ? extends ? extends for a non-general class. For example, List<Object> will contain any Object ? extends ? extends not required to add an object. A List<List<Foo>> will only accept List<Foo> objects, not List<FooSubclass> objects [Generic classes are not inherited based on their parameters]. Here ? extends ? extends comes into play. To add both List<Foo> and List<FooSubclass> to List , the type must be List<List<? extends Foo>> List<List<? extends Foo>> .

+20
source share

Map<String, List<String> not working? Is there any special reason you should have a wildcard?

+6
source share

There is a very simple principle when sharing Collections and generics. It is called the "Principle of Get and Put Put":

Use the "extends" wildcard when you only expose the GET from the collection, use the "super" wildcard when you only add values ​​to the collection and do not use any wildcard if you want it to be received and put.

So, as you can see, the original example is not valid according to this principle.

+4
source share

Imagine someone passing you Map<String, ArrayList<String>> . The value you insert is the result of Collections.singletonList, which is not an ArrayList .

You cannot accept any subtype of the list on the map, and then expect that you can add your own, possibly incompatible subtype.

0
source share

All Articles