我怎样才能转换 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);
我怎样才能转换 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);
现在我们有了 Java 8/streams,我们可以在列表中再添加一个可能的答案:
假设每个值实际上都是 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()));
如果您Objects
只包含 of 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()
.
泛型类型是一种编译时抽象。在运行时,所有地图都将具有相同的类型Map<Object, Object>
。因此,如果您确定值是字符串,则可以在 java 编译器上作弊:
Map<String, Object> m1 = new HashMap<String, Object>();
Map<String, String> m2 = (Map) m1;
将键和值从一个集合复制到另一个集合是多余的。但是这种方法仍然不好,因为它违反了泛型类型安全。可能您应该重新考虑您的代码以避免此类事情。
有两种方法可以做到这一点。一种非常简单但不安全:
Map<String, Object> map = new HashMap<String, Object>();
Map<String, String> newMap = new HashMap<String, String>((Map)map); // unchecked warning
另一种方式没有编译器警告并确保运行时的类型安全,更加健壮。(毕竟,你不能保证原始地图只包含 String 值,否则为什么不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);
不可能。
这有点违反直觉。
你遇到“苹果是水果”但“每个水果都不是苹果”
去创建一个新地图并检查instance of with String
当您从 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");
}
}
使用 Java 8 将 a 转换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()));
以下将转换您现有的条目。
TransformedMap.decorateTransform(params, keyTransformer, valueTransformer)
然而
MapUtils.transformedMap(java.util.Map map, keyTransformer, valueTransformer)
仅将新条目转换为您的地图
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;
}
这里有很好的解决方案,只是考虑处理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()));
虽然您可以通过暴力转换和抑制警告来做到这一点
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
(!!) 进行了前半部分的处理,然后决定使用正确的类型作为 a 进行后半部分,因此您从toString
缩小范围。幸运的是,你可以用 java 来做到这一点(在这种情况下很容易)——但这只是掩盖了你在前半部分使用弱类型的事实。不好的做法,没有争论。Object
String
这里没有区别(只是更难施展)。您应该始终使用强类型。至少使用一些基本类型 - 然后可以使用泛型通配符(“?extends BaseType”或“?super BaseType”)来提供类型兼容性和自动转换。更好的是,使用正确的已知类型。除非你有 100% 可以真正用于任何类型的通用代码,否则永远不要使用 Object。
希望有帮助!:) :)
注意: 通用强类型和类型转换仅存在于 .java 代码中。编译为 .class 后,我们留下了没有泛型类型参数以及键和值的自动类型转换的原始类型(Map 和 HashMap)。但这很有帮助,因为 .java 代码本身是强类型且简洁的。
我发现使用番石榴最简单的方法:
<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());