3

什么是最简单/最好的转换方式

Map<String, Object>

HashMap<String, String>

我使用的 API 具有返回 Map 的方法,但如果我不必每次都将 Object 转换为 String 会更容易。

另外,这还值得吗?HashMap 会比 Map 更快/更高效吗?

我假设我必须遍历原始 Map 并将值复制到新的 HashMap。

提前致谢!

4

3 回答 3

10

您可以像其他人提到的那样使用构造函数:

Map<String, String> newMap = new HashMap(oldMap);

但是,这只有在您知道所讨论的Objects确实 String是 s 时才有效。

但有一点我应该提一下:

不要将接口混淆。Map只是一个界面;仅包含定义的合同。另一方面,类是接口的具体实现因此,如果您使用接口或其运行时类型 ( ) ,它在性能方面没有任何区别。但是,如果您交换实现(例如),它可能会有所不同。Map HashMapTreeMap

编辑:

这是 EE 人员喜欢的详细解决方案(不涉及强制转换/原始类型警告):

public class MapConverter {
    public Map<String, String> convert(Map<String, Object> oldMap) {
        Map<String, String> ret = new HashMap<String, String>();
        for (String key : oldMap.keySet()) {
            ret.put(key, oldMap.get(key).toString());
        }
        return ret;
    }
}
于 2013-07-16T23:02:05.410 回答
2

在原始类型上使用复制构造函数有效:

HashMap<String, String> hashMap = new HashMap(map);

但是,由于忽略了类型系统,因此该解决方案很难看。

编辑1:

当你执行

public static void main(String[] args) throws IllegalArgumentException,
        InterruptedException, IOException {
    HashMap<String, Object> map = new HashMap<String, Object>();
    map.put("Bla", new Object());
    HashMap<String, String> hashMap = new HashMap(map);
    System.out.println(hashMap.get("Bla").getClass());
}

你得到类转换异常:

Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String

当 "System.out.println(hashMap.get("Bla").getClass());" 时抛出它 被执行。

因此,演员阵容实际上被推迟了。

编辑2:

你可以避免复制

HashMap<String, String> hashMap = (HashMap)map;

但是,问题仍然与以下代码所示相同:

public static void main(String[] args) throws IllegalArgumentException,
        InterruptedException, IOException {
    HashMap<String, Object> oldMap = new HashMap<String, Object>();
    oldMap.put("Bla", new Object());
    HashMap<String, String> hashMap = (HashMap)oldMap;
    System.out.println(hashMap.get("Bla").getClass());
}

它的行为类似于上面 EDIT1 中的另一个示例。

EDIT3:使用 lambda 怎么样?

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

    // 1

    final Stream<Map.Entry<String, Object>> entries = map.entrySet()
            .stream();

    final Function<Map.Entry<String, Object>, String> keyMapper = (
            Map.Entry<String, Object> entry) -> entry.getKey();

    final Function<Map.Entry<String, Object>, String> valueMapper = (
            Map.Entry<String, Object> entry) -> {
        final Object value = entry.getValue();
        if (value instanceof String) {
            return (String) value;
        } else {
            throw new ClassCastException("Value '" + value + "' of key '"
                    + entry.getKey() + "' cannot be cast from type "
                    + ((value != null) ? value.getClass().getName() : null)
                    + " to type " + String.class.getName());
        }
    };

    final BinaryOperator<String> duplicateHandler = (key1, key2) -> {
        throw new IllegalStateException(String.format("Duplicate key %s",
                key1));
    };

    final HashMap<String, String> hashMap = entries.collect(Collectors
            .toMap(keyMapper, valueMapper, duplicateHandler, HashMap::new));

    System.out.println(hashMap);

如果 map 只有字符串到字符串的条目,它将全部复制。例如插入

    map.put("aKey", "aValue");

在评论 1. 它将打印

    {aKey=aValue}

这很好。

如果您的地图中至少有一个字符串到非字符串条目,则复制将失败。

例如插入

    map.put("aKey", 42);

在评论 1. 它将打印

Exception in thread "main" java.lang.ClassCastException: Value '42' of key ' aKey' cannot be cast from type java.lang.Integer to type java.lang.String
    at ...

它显示了字符串到非字符串条目。

我知道这个解决方案不是那么简单,但它是安全的。

于 2013-07-16T23:04:10.630 回答
0

如果您知道键和值的类型(如<String, String>),则可以转换整个映射:

Map<String, String> newMap = (HashMap<String, String>)oldMap;

如果你需要一个单独的Map实例,你可以使用这样的构造函数HashMap

HashMap<String, String> = new HashMap<String, String>((HashMap<String, String>) oldMap);
于 2013-07-16T22:58:37.010 回答