我有两个地图,其关键是String
s,其值是Set<MyObject>
。给定两个Map
s,合并它们的最简单方法是什么,以便如果两个密钥相同,则该值是两个集合的并集。您可以假定值不会为空,如果它有用,我们可以使这些值成为Map
s SortedMap
s。合并两个地图
合并两个地图
回答
我们在谈论HashMap
实例。在这种情况下,查找是O(1),因此您可以只取一张地图,遍历该地图的条目,查看其他地图是否包含该关键字。如果不是,只需添加该组。如果它包含的钥匙,拿着两套联盟(由一组到另一个的adding all elements)
要使用一些代码,我在那里用了一套具有自动完成我的IDE说明
Map<String, Set<Double>> firstMap = new HashMap<String, Set<Double>>();
Map<String, Set<Double>> secondMap = new HashMap<String, Set<Double>>();
Set<Map.Entry<String, Set<Double>>> entries = firstMap.entrySet();
for (Map.Entry<String, Set<Double>> entry : entries) {
Set<Double> secondMapValue = secondMap.get(entry.getKey());
if (secondMapValue == null) {
secondMap.put(entry.getKey(), entry.getValue());
}
else {
secondMapValue.addAll(entry.getValue());
}
}
这将跳过secondMap中存在的条目,但不会在firstMap – sam 2013-05-13 06:21:03
sam中 - 他正在编辑secondMap,因此将更改secondMap。 – JFK 2015-02-23 15:15:36
你可以使用--addAll方法 http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html 但总是有这个问题 - 如果你的两个散列图有任何关键字都相同 - 那么它将使用第二个哈希映射中的键的值覆盖第一个哈希映射中的键的值。 对于更安全的一面 - 更改键值 - 可以在键上使用前缀或后缀 - (第一个哈希映射使用不同的前缀/后缀,第二个哈希映射使用不同的前缀/后缀) – 2016-03-16 06:25:15
以下应合并一个map1
到map2
(未经测试):
for (Entry<String, Set<???>> entry : map1.entrySet())
{
Set<???> otherSet = map2.get(entry.getKey());
if (otherSet == null)
map2.put(entry.getKey(), entry.getValue ());
else
otherSet.addAll(entry.getValue());
}
我不知道你在,因此<???>
参数您Set
S:适当更换。
这个怎么样(未经测试):
Map<String,Set<Whatever>> m1 = // input map
Map<String,Set<Whatever>> m2 = // input map
Map<String,Set<Whatever>> ret = // new empty map
ret.putAll(m1);
for(String key : m2.keySet()) {
if(ret.containsKey(key)) {
ret.get(key).addAll(m2.get(key));
} else {
ret.put(key,m2.get(key));
}
}
此解决方案不修改输入地图,因为它是短暂的,只有依靠API方法,我觉得相当的可读性。
请注意,putAll()
和addAll()
都是Map
和Set
中的可选方法。因此(为了得到O(1)查找),我建议使用HashMap
和HashSet
。
请注意,因为HashSet
或HashMap
都未同步,所以如果您需要线程安全代码,则需要寻找其他解决方案。
像这样(未经):
// Assume all maps are of the same generic type.
public static Map<String, Set<MyObject>> mergeAll(Map m1, Map m2) {
Map<String, Set<MyObject>> merged = new HashMap();
// Merge commom entries into the new map.
for (Map.Entry<String, Set<MyObject>> entry : m1.entrySet()) {
String key = entry.getKey();
Set<MyObject> s1 = new HashSet(entry.getValue());
Set<MyObject> s2 = m2.get(key);
if (s2 != null) s1.addAll(s2);
merged.put(key, s1);
}
// Add entries unique to m2 to the new map.
for (String key : m2.keys()) {
if (!s1.containsKey(key)) merged.put(key, new HashSet(m2.get(key)));
}
return merged;
}
请注意,此解决方案不发生变异或者它的参数。
那些在' m2'但不在'm1'中? – 2012-01-09 22:33:54
您可以调用'm2.getValue()',但'm2'是一个'Map',因此没有'getValue()'方法。 – 2012-01-09 22:40:59
@MichaelMcGowan:哦,对,修正了这个问题(geez,看看会发生什么事情,当我尝试编码掉头顶!) – maerics 2012-01-09 22:43:28
Map<Integer,String> m1=new HashMap<Integer,String>();
Map<Integer,String> m2=new HashMap<Integer,String>();
m1.put(1,"one");
m1.put(2,"two");
m2.put(3,"three");
m2.put(2,"two");
Set<Integer> s=m2.keySet();
for(int i:s){
if(m1.get(i)==null){
m1.put(i,m2.get(i));
}
}
System.out.println(m1);
这是一个简单的程序,解释如何合并两个地图 – user3301756 2014-02-12 13:10:09
注意,所有其他的答案最终会增加,你可能不希望所有用例的原套,如果你不想只是使用第三映射作为输出,并创建一套新的每个键
public static void merge2Maps(Map<String, Set<Double>> a, Map<String, Set<Double>> b, Map<String, Set<Double>> c){
for (Map.Entry<String, Set<Double>> entry : a.entrySet()) {
Set<Double> set = new HashSet<Double>();
c.put(entry.getKey(), set);
set.addAll(entry.getValue());
}
for (Map.Entry<String, Set<Double>> entry : b.entrySet()) {
String key = entry.getKey();
Set<Double> set = c.get(key);
if (set == null) {
set = new HashSet<Double>();
c.put(entry.getKey(), set);
}
set.addAll(entry.getValue());
}
}
您可以用stream做到这一点很容易:
Map<T, Set<U>> merged = Stream.of(first, second)
.map(Map::entrySet)
.flatMap(Set::stream)
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> {
HashSet<U> both = new HashSet<>(a);
both.addAll(b);
return both;
}));
此拆分映射到他们Entry
秒,然后用01加入他们其中resolves duplicates通过将这两个值添加到新的HashSet
。
这也适用于任何数量的地图。
其产生相同的结果的一些变化:
Stream.of(first, second).flatMap(m -> m.entrySet().stream())
.collect(...);
Stream.concat(first.entrySet().stream(), second.entrySet().stream())
.collect(...); //from comment by Aleksandr Dubinsky
为Collectors.toMap
第三个参数是没有必要的,如果没有重复的密钥。
还有另一个Collectors.toMap
与第四个参数,让您决定收集到Map
的类型。
更简洁一点就是使用' Stream.concat(first.entrySet()。stream(),second.entrySet()。stream())'并且避免'map'和'flatMap'。 – 2015-03-03 11:00:17
如果你想结束不可变的数据结构,以防止操纵你的合并地图和地图的Set实例,那么你可以采取这种方法。该解决方案使用Google的Guava库。
public <K,T> Map<K, Set<T>> mergeToImmutable (
final Map<K, Set<T>> left,
final Map<K, Set<T>> right)
{
return Maps.toMap(
Sets.union(
checkNotNull(left).keySet(),
checkNotNull(right).keySet()
),
new Function<K, Set<T>>() {
@Override
public Set<T> apply (K input) {
return ImmutableSet.<T>builder()
.addAll(MoreObjects.firstNonNull(left.get(input), Collections.<T>emptySet()))
.addAll(MoreObjects.firstNonNull(right.get(input), Collections.<T>emptySet()))
.build();
}
}
);
}
如果定义团结非空Set
个方法为:
static <T> Set<T> union(Set<T>... sets) {
return Stream.of(sets)
.filter(s -> s != null)
.flatMap(Set::stream)
.collect(Collectors.toSet());
}
然后合并具有Set<V>
值的两个映射m1
和m2
可以如下进行:
Map<String, V> merged
= union(m1.keySet(), m2.keySet())
.stream()
.collect(Collectors.toMap(k -> k, k -> union(m1.get(k), m2.get(k))));
或更简单:
Map<String, V> merged = new HashMap<>();
for (String k : union(m1.keySet(), m2.keySet())
merged.put(k, union(m1.get(k), m2.get(k)));
<K, V> Map<K, List<V>> mergeMapOfLists(Stream<Map<K, List<V>>> stream) {
return stream
.map(Map::entrySet) // convert each map to set of map's entries
.flatMap(Collection::stream) // convert each map entry to stream and flat them to one stream
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue,
(list1, list2) -> {
list1.addAll(list2);
return list1;
})); // convert stream to map; if key is duplicated execute merge fuction (append exisitng list with elements from new list)
}
static void mergeSet(Map<String, Set<String>> map1, Map<String, Set<String>> map2) {
map1.forEach((key1, value1) -> {
map2.merge(key1, value1, (key2, value2) -> key2).addAll(value1);
});
}
- 1. jvectormap合并两个地图
- 2. 合并两个地图C++
- 3. Clojure中,合并两个阵列地图
- 4. 合并两个地图<String,List>
- 5. 斯卡拉两个地图合并
- 6. 将多个地图合并/合并为1个地图
- 7. 合并两个arduino草图
- 8. 合并两个图像
- 9. 合并两个图像
- 10. 如何合并两张地图在Haskell
- 11. 合并多个Sass地图
- 12. 将两个地图合并为一个MultiMap
- 13. Mercurial:合并两个本地回购
- 14. 如何合并一个两个图像?
- 15. WriteableBitmapEx - 合并两个图像在一个
- 16. Android合并两张图像,另一张合并两张图像
- 17. 基于密钥合并两个地图的值
- 18. 在scala中合并两个嵌套的地图
- 19. 如何在Om Clojurescript中合并两个#js地图?
- 20. 在Clojure中,我如何合并两个地图向量?
- 21. 合并两个IGrouping集合
- 22. 合并两个Eloquent集合
- 23. 获取两个地图的结合
- 24. 合并两个UITableViewControllers
- 25. 合并两个表
- 26. 合并两个SortedLists
- 27. 合并两个表
- 28. 合并两个arraylists
- 29. 合并两个NSFetchedResultsController
- 30. 合并两个XElements
如果你必须使用番石榴[Multimap之(https://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap),你可以简单地避免这个问题的方法可行,合并和putAll(Multimap其他)一样简单。 – Dag 2015-05-29 15:22:56
类似,可能重复:http://stackoverflow.com/questions/4299728/how-can-i-combine-two-hashmap-objects-containing-the-same-types – 2015-08-20 18:20:39
应该很容易做到[地图合并](https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#merge-KV-java.util.function.BiFunction-)方法。 – Roland 2016-08-29 16:29:56