dev4life
dev4life

Reputation: 882

Putting into a Map<String, ?>

So I have a Map that has some values in it being passed into a method:

public String doThis(Map<String, ?> context){
.....
}

And I'm trying to insert an addition attribute to this Map

String abc="123";
context.put("newAttr",abc);

But I am getting this error:

The method put(String, capture#8-of ?) in the type Map is not applicable for the arguments (String, String)

Is there anyway to perform this put without "cloning" the Map?

Upvotes: 9

Views: 15383

Answers (3)

Jarekczek
Jarekczek

Reputation: 7866

Surprisingly we can convert this map into an easier to use form. Just with this simiple syntax: (Map<String, ObjectOrSth>)unfriendlyMap.

// Let's get this weird map.
HashMap<String, String> mapOrig = new HashMap<String, String>();
Map<String, ?> mapQuestion = (Map<String, ?>)mapOrig;
//mapQuestion.put("key2", "?"); // impossible

// Convert it to almost anything...
Map<String, String> mapStr2 = (Map<String, String>)mapQuestion;
mapStr2.put("key2", "string2");
assertThat(mapOrig.get("key2")).isEqualTo("string2");
Map<String, Object> mapObj = (Map<String, Object>)mapQuestion;
mapObj.put("key3", "object");
assertThat(mapOrig.get("key3")).isEqualTo("object");

Upvotes: 0

newacct
newacct

Reputation: 122429

Remember PECS (Producer Extends, Consumer Super). You have a consumer (putting in), therefore it cannot be extends.

Upvotes: 4

Adam Zalcman
Adam Zalcman

Reputation: 27233

If you want to put values of type X into a generic Map you need to declare the Map as Map<String, ? super X>. In your example X is String, so:

public String doThis(Map<String, ? super String> context){
.....
}

Map<String, ? super X> means: a map with keys of type String and values of a type which is X or a super-type of X. All such maps are ready to accept String instances as keys and X instances as values.

Upvotes: 12

Related Questions