什么是最简单/最好的转换方式
Map<String, Object>
至
HashMap<String, String>
我使用的 API 具有返回 Map 的方法,但如果我不必每次都将 Object 转换为 String 会更容易。
另外,这还值得吗?HashMap 会比 Map 更快/更高效吗?
我假设我必须遍历原始 Map 并将值复制到新的 HashMap。
提前致谢!
什么是最简单/最好的转换方式
Map<String, Object>
至
HashMap<String, String>
我使用的 API 具有返回 Map 的方法,但如果我不必每次都将 Object 转换为 String 会更容易。
另外,这还值得吗?HashMap 会比 Map 更快/更高效吗?
我假设我必须遍历原始 Map 并将值复制到新的 HashMap。
提前致谢!
您可以像其他人提到的那样使用构造函数:
Map<String, String> newMap = new HashMap(oldMap);
但是,这只有在您知道所讨论的Object
s确实 String
是 s 时才有效。
但有一点我应该提一下:
不要将接口与类混淆。Map
只是一个界面;仅包含定义的合同。另一方面,类是接口的具体实现。因此,如果您使用接口或其运行时类型 ( ) ,它在性能方面没有任何区别。但是,如果您交换实现(例如),它可能会有所不同。Map
HashMap
TreeMap
编辑:
这是 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;
}
}
在原始类型上使用复制构造函数有效:
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 ...
它显示了字符串到非字符串条目。
我知道这个解决方案不是那么简单,但它是安全的。
如果您知道键和值的类型(如<String, String>
),则可以转换整个映射:
Map<String, String> newMap = (HashMap<String, String>)oldMap;
如果你需要一个单独的Map
实例,你可以使用这样的构造函数HashMap
:
HashMap<String, String> = new HashMap<String, String>((HashMap<String, String>) oldMap);