将Map<String, Object>轻松转换为Map<String, String>

6
我正在使用的 API 有一个返回 Map<String, Object> 的方法,但我知道在这种情况下 ObjectString,所以我希望它是一个 Map<String, String>
但由于某些原因,我无法直接进行转换,Java 提示无法将 Map<String, Object> 强制转换为 Map<String, String>
我尝试了以下代码:
Map<String, Object> tempMap = someApiMethodReturningAMap();
Map<String, String> map = new HashMap<String, String>();
for (String i : tempMap.keySet()) {
    map.put(i, String.valueOf(tempMap.get(i)));
}

作为一种解决方法,但是否有更简单的方式?

3
很简单易懂,我只建议将类型转换为"String.valueOf()"——您需要为参数的toString()方法编写一个有意义的实现。 - hovanessyan
@hovanessyan 谢谢,已编辑。 - jobukkit
3个回答

12

你不能安全地将它强制转换为Map<String, String>,因为尽管您知道值只是字符串,但编译器并不知道。这就像期望:

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

要使用它并不起作用;您需要 显式地 转换。

同样,如果通过 Object 进行,您也可以在此处显式转换:

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

现在你会收到一个警告,提示这是一个未经检查的转换,因为与之前的“对象到字符串”的转换不同,没有执行时检查其是否真实有效。类型擦除意味着map并不真正知道它的键/值类型。因此,只有在获取元素时才会进行检查:

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"));
    }
}

如果您真的想避免创建新地图,则此“通过 Object 进行转换”的方法可行,但远非理想。

您的方法更安全,不过可以通过避免查找使其稍微更高效:

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;
}

8

一个Java 8的解决方案:

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

2

这里有一些好的解决方案,但我想再添加一个考虑到处理 null 值的方法:

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()));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接