[ACCEPTED]-Easily convert Map<String, Object> to Map<String, String>-casting

Accepted answer
Score: 12

Well you can't safely cast it to a Map<String, String> because even 17 though you know you've only got strings as 16 the values, the compiler doesn't. That's 15 like expecting:

Object x = "foo";
String y = x;

to work - it doesn't; you 14 need to explicitly cast.

Likewise you can explicitly 13 cast here, too, if you go via Object:

Map<String, Object> x = ...;
Map<String, String> y = (Map<String, String>) (Object) x;

Now you'll 12 get a warning saying that it's an unchecked cast, because 11 unlike the earlier "object to string" cast, there's 10 no execution-time check that it's really 9 valid. Type erasure means that a map doesn't 8 really know its key/value types. So you 7 end up with checking only being done when 6 elements are fetched:

import java.util.*;

class Test {
    public static void main(String[] args) {
        Map<String, Object> x = new HashMap<>();
        x.put("foo", "bar");
        x.put("number", 0);
        Map<String, String> y = (Map<String, String>) (Object) x;
        // This is fine
        System.out.println(y.get("foo"));

        // This goes bang! It's trying to cast an Integer to a String
        System.out.println(y.get("number"));
    }
}

So if you really want 5 to avoid creating a new map, this "cast 4 via Object" will work - but it's far from ideal.

Your 3 approach is safer, although you can make 2 it slightly more efficient by avoiding the 1 lookup:

public static Map<String, String> copyToStringValueMap(
        Map<String, Object> input) {
    Map<String, String> ret = new HashMap<>();
    for (Map.Entry<String, Object> entry : input.entrySet()) {
        ret.put(entry.getKey(), (String) entry.getValue());
    }
    return ret;
}
Score: 7

A Java 8 solution:

private Map<String, String> stringifyValues(Map<String, Object> variables) {
    return variables.entrySet().stream()
            .collect(Collectors.toMap(Map.Entry::getKey, e -> (String) e.getValue()));
}

0

Score: 2

Good solutions here, but I want to add another 2 one that taking into consideration handling 1 null values:

Map<String,Object> map = new HashMap<>();

Map<String,String> stringifiedMap = map.entrySet().stream()
             .filter(m -> m.getKey() != null && m.getValue() !=null)
             .collect(Collectors.toMap(Map.Entry::getKey, e -> (String)e.getValue()));

More Related questions