[英]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.