[英]Generate an Map containing an Intersection/Union of values contained in two maps Map<X,Set<Y>>
我有两个地图参数: Map<X,Set<Y>> map1
和Map<X,Set<Y>> map2
。
我正在寻找一种方法来编写一种方法,该方法生成一个新映射,其中包含两个映射中都存在的键的值的交集,以及map1
或map2
中存在的键的值的联合。
换句话说,对于任何X x
如果它在map1
的域中但不在map2
的域中,那么它的值将是map1.get(x)
。 在相反的情况下也一样。 如果它在它们两个中,那么我想返回一个集合,它是map1.get(x)
和map2.get(x)
的交集。
假设我知道X
是哪个类,这可以通过以下代码完成:
public Map<X,Set<Y>> unifyAndIntersect(Map<X,Set<Y>> map1, Map<X,Set<Y>> map2) {
Map<X,Set<Y>> combined = new HashMap();
combined.putAll(map1);
for(X x : map2.keySet()){
if(combined.contains(x)){
Set<Y> res = Sets.newSet();
res.addAll(map1.get(x));
res.retainAll(map2.get(x));
combined.put(x,res);
}
else{
combined.put(x,map2.get(x));
}
}
}
但是,我想让这个方法通用,从某种意义上说它适用于任何X
和Y
。 我曾尝试使用Object
,但从我的类类型转换为Object
时出错...
你能告诉我什么是正确的方法吗?
为了声明一个泛型方法,您需要在方法修饰符和返回类型之间提供泛型类型参数<X,Y>
( 有关更多信息,请参阅)。 没有映射类型Map<X,Set<Y>>
中的X
和Y
将不会被视为类型的通用“占位符”,但作为类型本身和编译器会抱怨类型X
和Y
是未知的。
不要忘记右侧的菱形<>
,同时实例化一个泛型类, new HashMap();
没有菱形会创建一个行类型的地图。
您提供的代码中也存在不一致:如果两个映射都存在一个键,则会将一个新集合作为值添加到结果映射中,但是如果根据您的代码键仅包含在其中一个中将使用现有的集合。 我最好通过为每个值生成一个新集合来确保对结果映射值的后续修改不会影响map1
和map2
的状态。
public <X,Y> Map<X, Set<Y>> unifyAndIntersect(Map<X,Set<Y>> map1,
Map<X,Set<Y>> map2) {
Map<X, Set<Y>> combined = new HashMap<>();
for(Map.Entry<X, Set<Y>> entry: map1.entrySet()){
Set<Y> union = new HashSet<>(entry.getValue());
if (map2.containsKey(entry.getKey())) {
union.retainAll(map2.get(entry.getKey()));
}
combined.put(entry.getKey(), union);
}
return combined;
}
使用 Stream API 可以实现相同的逻辑:
public <X,Y> Map<X, Set<Y>> unifyAndIntersect(Map<X,Set<Y>> map1,
Map<X,Set<Y>> map2) {
return map1.entrySet().stream()
.map(entry -> {
Set<Y> set2 = map2.get(entry.getKey());
return set2 == null ? Map.entry(entry.getKey(), new HashSet(entry.getValue())) :
Map.entry(entry.getKey(),
entry.getValue().stream()
.filter(set2::contains)
.collect(Collectors.toSet()));
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.