如何将Map<String,Object>
转换为Map<String,String>
?
这不起作用:
Map<String,Object> map = new HashMap<String,Object>(); //Object is containing String
Map<String,String> newMap =new HashMap<String,String>(map);
答案 0 :(得分:33)
现在我们有Java 8 /流,我们可以在列表中再添加一个答案:
假设实际的每个值都是 String
个对象,那么转换为String
应该是安全的。否则,可以使用一些其他机制将对象映射到字符串。
Map<String,Object> map = new HashMap<>();
Map<String,String> newMap = map.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> (String)e.getValue()));
答案 1 :(得分:23)
如果您的Objects
仅包含Strings
,那么您可以这样做:
Map<String,Object> map = new HashMap<String,Object>(); //Object is containing String
Map<String,String> newMap =new HashMap<String,String>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
if(entry.getValue() instanceof String){
newMap.put(entry.getKey(), (String) entry.getValue());
}
}
如果每个Objects
都不是String
,那么您可以将(String) entry.getValue()
替换为entry.getValue().toString()
。
答案 2 :(得分:18)
泛型类型是编译时抽象。在运行时,所有映射都将具有相同的类型Map<Object, Object>
。因此,如果你确定值是字符串,你可以欺骗java编译器:
Map<String, Object> m1 = new HashMap<String, Object>();
Map<String, String> m2 = (Map) m1;
将密钥和值从一个集合复制到另一个集合是多余的。但这种方法仍然不好,因为它违反了泛型类型的安全性。也许你应该重新考虑你的代码以避免这些事情。
答案 3 :(得分:5)
有两种方法可以做到这一点。一个很简单但不安全:
Map<String, Object> map = new HashMap<String, Object>();
Map<String, String> newMap = new HashMap<String, String>((Map)map); // unchecked warning
另一种方式没有编译器警告,并确保运行时类型安全,这更加强大。 (毕竟,你不能保证原始地图只包含字符串值,否则为什么它首先不是Map<String, String>
?)
Map<String, Object> map = new HashMap<String, Object>();
Map<String, String> newMap = new HashMap<String, String>();
@SuppressWarnings("unchecked") Map<String, Object> intermediate =
(Map)Collections.checkedMap(newMap, String.class, String.class);
intermediate.putAll(map);
答案 4 :(得分:2)
不可能。
这有点反直觉。
你遇到的是“Apple is-a fruit”,但“Every Fruit is not a Apple”
创建新地图并使用instance of with String
答案 5 :(得分:2)
当你从Object转换为String时,我建议你捕获并报告(在某种程度上,这里我只打印一条消息,这通常很糟糕)例外。
Map<String,Object> map = new HashMap<String,Object>(); //Object is containing String
Map<String,String> newMap =new HashMap<String,String>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
try{
newMap.put(entry.getKey(), (String) entry.getValue());
}
catch(ClassCastException e){
System.out.println("ERROR: "+entry.getKey()+" -> "+entry.getValue()+
" not added, as "+entry.getValue()+" is not a String");
}
}
答案 6 :(得分:1)
虽然您可以使用暴力投射和抑制警告来执行此操作
Map<String,Object> map = new HashMap<String,Object>();
// Two casts in a row. Note no "new"!
@SuppressWarnings("unchecked")
Map<String,String> newMap = (HashMap<String,String>)(Map)map;
这真的错过了重点。 :)
尝试将窄泛型类型转换为更广泛的泛型类型意味着您首先使用了错误的类型。
作为一个类比:想象一下,你有一个程序可以进行丰富的文本处理。想象一下,使用Objects
(!!)执行前半部分处理,然后决定使用正确输入作为String
进行后半部分,因此您可以从Object
缩小范围到String
。幸运的是,你可以做到这一点是java(在这种情况下很容易) - 但它只是掩盖了你在上半场使用弱类型的事实。不好的做法,没有争论。
这里没有区别(只是更难施展)。你应该总是使用强类型。至少使用一些基本类型 - 然后可以使用泛型通配符(“?extends BaseType”或“?super BaseType”)来提供类型兼容性和自动转换。更好的是,使用正确的已知类型。除非你有100%可以真正用于任何类型的通用代码,否则永远不要使用Object。
希望有所帮助! :):)
注意:通用的强类型和类型转换只存在于.java代码中。在编译成.class之后,我们留下了原始类型(Map和HashMap),没有泛型类型参数以及键和值的自动类型转换。但它非常有用,因为.java代码本身是强类型和简洁的。
答案 7 :(得分:1)
以下内容将转换您现有的条目。
TransformedMap.decorateTransform(params, keyTransformer, valueTransformer)
在哪里
MapUtils.transformedMap(java.util.Map map, keyTransformer, valueTransformer)
只会将新条目转换为您的地图
答案 8 :(得分:1)
这里有很好的解决方案,只考虑处理document.getElementById("todoListUL").innerHTML = todoArray.join("");
值的另一个选项:
null
答案 9 :(得分:1)
我发现最简单的方法是使用番石榴:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1-jre</version>
</dependency>
那么你可以这样做:
Map<String,Object> map = new HashMap<String,Object>();
Map<String,String> newMap = Maps.transformValues(map, Functions.toStringFunction());
答案 10 :(得分:0)
private Map<String, String> convertAttributes(final Map<String, Object> attributes) {
final Map<String, String> result = new HashMap<String, String>();
for (final Map.Entry<String, Object> entry : attributes.entrySet()) {
result.put(entry.getKey(), String.valueOf(entry.getValue()));
}
return result;
}
答案 11 :(得分:0)
使用Java 8将Map<String, Object>
转换为Map<String, String>
的方式。此解决方案处理null
个值。
Map<String, String> keysValuesStrings = keysValues.entrySet().stream()
.filter(entry -> entry.getValue() != null)
.collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().toString()));