java 如何将 HashMap<K, V> 值类型从 Object 更改为 String?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17688323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 14:40:47  来源:igfitidea点击:

How to change HashMap<K, V> value type from Object to String?

javadictionarydata-structureshashmaptype-conversion

提问by Connor

What is the easiest/best way to convert

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

Map<String, Object>

to

HashMap<String, String>

The API I am using has methods that return a Map but it would be easier if I didn't have to cast the Object to a String each time.

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

Also, is this even worth doing? Would a HashMap be faster/more efficient than a Map?

此外,这甚至值得吗?HashMap 会比 Map 更快/更有效吗?

I'm assuming I'll have to loop through the original Map and copy the values to the new HashMap.

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

Thanks in advance!

提前致谢!

回答by Adam Arold

You can use the constructor as others mentioned:

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

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

This will only work however if you know that the Objects in question are reallyStrings.

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

but there is something I should mention:

但有一点我应该提一下:

Do not confuse interfaceswith classes. Mapis just an interface; a contractwhich contains only definitions. A classon the other hand is a concrete implementationof an interface. So it does not make any difference in terms of perfomrance if you use the Mapinterfaceor its runtime type (HashMap). It can make a difference however if you swap the implementations (to TreeMapfor example).

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

Edit:

编辑:

Here is the verbose solution which is liked by EE guys (no casting/rawtypes warning involved):

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

回答by mmirwaldt

Using the copy constructor on raw types works:

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

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

However, the solution is ugly as the type system is ignored.

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

EDIT1:

编辑1:

When you execute

当你执行

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

you get the class cast exception:

你得到类转换异常:

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

It is thrown when "System.out.println(hashMap.get("Bla").getClass());" is executed.

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

Consequently, the casts are actually delayed.

因此,演员表实际上被延迟了。

EDIT2:

编辑2:

You can avoid the copy with

你可以避免复制

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

However, the problem remains the same as the following code shows:

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

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

It behaves like the other example above in EDIT1.

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

EDIT3: What about using a lambda?

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

If map only has string-to-string entries, it will copy them all. E.g. Insert

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

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

at comment 1. It will print

在评论 1. 它会打印

    {aKey=aValue}

which is fine.

这很好。

If you have at least one string-to-non-string entry in your map, copying will fail.

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

E.g. Insert

例如插入

    map.put("aKey", 42);

at comment 1. It will print

在评论 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 ...

which shows the string-to-non-string entry.

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

I know this solution is not so simple but it is safe.

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

回答by f1sh

If you know the types of key and value (like <String, String>), you can just cast the whole map:

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

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

If you need a separate Mapinstance, you can use the constructor of HashMaplike this:

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

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