Java 映射与泛型的递归合并
我正在尝试构建一种方法来合并两个地图的内容。我已经在这里四处寻找了一段时间,但找不到一个通用的方法。我希望尽可能避免使用Java 映射与泛型的递归合并,java,generics,recursion,Java,Generics,Recursion,我正在尝试构建一种方法来合并两个地图的内容。我已经在这里四处寻找了一段时间,但找不到一个通用的方法。我希望尽可能避免使用@SuppressWarnings(“未选中”)注释。我有一个嵌套的映射结构,其中键是字符串,值是更多内容的映射,该结构中的“叶”节点始终是集合。所以在大多数情况下,我有两个结构类似的地图: Map<String,Map<String,Set<String>>> public <T extends Map<String,
@SuppressWarnings(“未选中”)
注释。我有一个嵌套的映射结构,其中键是字符串,值是更多内容的映射,该结构中的“叶”节点始终是集合。所以在大多数情况下,我有两个结构类似的地图:
Map<String,Map<String,Set<String>>>
public <T extends Map<String,T>> Map<String,T> merge(final T map1, final T map2)
Map
我想合并这两个映射,这样我就得到了这两个映射的并集,这两个映射中的任何公共键都在结果映射中用一个值表示,该值是两个映射中两个值的合并。在代码中,这是我到目前为止所做的:
@SuppressWarnings("unchecked")
public Map<String,Object> merge(final Map<String, Object> map1,
final Map<String, Object> map2) {
final Map<String,Object> merged = new HashMap<String,Object>(map1);
for (final Map.Entry<String,Object> entry : merged.entrySet()) {
final String key = entry.getKey();
final Object value = entry.getValue();
if (map2.containsKey(key)) {
final Object value2 = map2.get(key);
if ((value instanceof Map) && (value2 instanceof Map)) {
merged.put(key, merge((Map<String, Object>) value, (Map<String, Object>) value2));
} else if ((value instanceof Set) && (value2 instanceof Set)) {
final Set<Object> set = new HashSet<Object>((Set<Object>)value);
set.addAll((Set<Object>) value2);
merged.put(key, set);
} else {
// throw up, should only ever be a map or a set
}
}
}
for (final String key : map2.keySet()) {
if (!merged.containsKey(key)) {
merged.put(key, map2.get(key));
}
}
return merged;
}
@SuppressWarnings(“未选中”)
公共地图合并(最终地图地图1,
最终地图(地图2){
最终映射合并=新HashMap(map1);
对于(最终映射.Entry:merged.entrySet()){
最后一个字符串key=entry.getKey();
最终对象值=entry.getValue();
if(地图2.containsKey(图例)){
最终对象值2=map2.get(键);
if((映射的值实例)和&(映射的值2实例)){
merged.put(key,merge((Map)value,(Map)value2));
}else if((集合的值实例)和&(集合的值2实例)){
最终集=新哈希集((集)值);
set.addAll((set)值2);
合并。放置(键,集);
}否则{
//呕吐,应该是一张地图或一套
}
}
}
for(最终字符串键:map2.keySet()){
如果(!merged.containsKey(键)){
merged.put(key,map2.get(key));
}
}
返回合并;
}
它确实起到了作用,但我对它不满意,因为使用它时,你会抛出一大堆东西,它还会对你正在使用的集合和映射实现进行假设。假设我知道我一直在处理字符串到某个对象的映射,其中某个对象是一组字符串或另一个字符串到某个对象的映射,我试图找出如何使用泛型来规范这一点。我尝试了其他答案中显示的类似但不完全相同的方法,例如方法签名,如:
Map<String,Map<String,Set<String>>>
public <T extends Map<String,T>> Map<String,T> merge(final T map1, final T map2)
公共地图合并(最终T地图1,最终T地图2)
但这并没有成功,因为递归调用不喜欢我尝试输入映射为的参数
我承认以前从来没有必要深入研究泛型。非常感谢您的指导。我们正在对您正在使用的集合和映射实现进行假设:如果您总是创建新的映射和集合,您至少可以避免这种情况——这有一个很好的副作用,即如果有人修改原始集合,就不会破坏您的合并版本
至于您的主要观点,在Java中,没有强制转换就无法做到这一点。泛型不能帮助您,因为在运行时,编译器只知道
Map<String, Object> merge ( Map<String, ?> map1, Map<String, ?> map2 )
我认为你的问题是递归,而不是你提到的T型。Java在泛型中使用enumerate,这意味着当您在运行时执行代码时,类型T将是一个对象。最简单的解决方案可能是使用Map
作为叶子。@Lonenebula您的意思是Map
?@Paul我的意思是他可以对所有节点使用T extends Map
,但是在节点是叶子的情况下,值部分被设置为null
@Paul不要紧,有些映射不允许null
-values。是的,我同意,我不认为泛型是解决这个问题的方法。