我有两个HashMap对象定义如下:
HashMap<String, Integer> map1 = new HashMap<String, Integer>();
HashMap<String, Integer> map2 = new HashMap<String, Integer>();
Run Code Online (Sandbox Code Playgroud)
我还有第三个HashMap对象:
HashMap<String, Integer> map3;
Run Code Online (Sandbox Code Playgroud)
我该如何合并map1,并map2汇集成map3?
a_h*_*ame 325
map3 = new HashMap<>();
map3.putAll(map1);
map3.putAll(map2);
Run Code Online (Sandbox Code Playgroud)
Jef*_*oom 102
如果您知道没有重复键,或者您希望值map2覆盖map1重复键的值,则可以编写
map3 = new HashMap<>(map1);
map3.putAll(map2);
Run Code Online (Sandbox Code Playgroud)
如果您需要更多地控制值的组合方式,可以使用Map.mergeJava 8中添加的,它使用用户提供的方法BiFunction来合并重复键的值. merge对单个键和值进行操作,因此您需要使用循环或Map.forEach.这里我们连接重复键的字符串:
map3 = new HashMap<>(map1);
for (Map.Entry<String, String> e : map2.entrySet())
map3.merge(e.getKey(), e.getValue(), String::concat);
//or instead of the above loop
map2.forEach((k, v) -> map3.merge(k, v, String::concat));
Run Code Online (Sandbox Code Playgroud)
如果您知道自己没有重复的密钥并希望强制执行它,则可以使用抛出以下内容的合并函数AssertionError:
map2.forEach((k, v) ->
map3.merge(k, v, (v1, v2) ->
{throw new AssertionError("duplicate values for key: "+k);}));
Run Code Online (Sandbox Code Playgroud)
从这个特定问题退一步,Java 8流库提供toMap和groupingBy 收集器.如果您在循环中反复合并映射,则可以重构计算以使用流,这既可以澄清您的代码,又可以使用并行流和并发收集器实现轻松并行.
Vit*_*nko 45
使用Java 8 Stream API的单线程:
map3 = Stream.of(map1, map2).flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue))
Run Code Online (Sandbox Code Playgroud)
此方法的好处之一是能够传递合并函数,该函数将处理具有相同键的值,例如:
map3 = Stream.of(map1, map2).flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, Math::max))
Run Code Online (Sandbox Code Playgroud)
Vad*_*zim 34
用于合并两个映射的Java 8替代单行程序:
defaultMap.forEach((k, v) -> destMap.putIfAbsent(k, v));
Run Code Online (Sandbox Code Playgroud)
与方法参考相同:
defaultMap.forEach(destMap::putIfAbsent);
Run Code Online (Sandbox Code Playgroud)
或者使用第三张地图的原始地图解决方案的idemponent:
Map<String, Integer> map3 = new HashMap<String, Integer>(map2);
map1.forEach(map3::putIfAbsent);
Run Code Online (Sandbox Code Playgroud)
这里有一种方法可以将两个映射合并到具有最少可能的中间复制操作的Guava的快速不可变映射中:
ImmutableMap.Builder<String, Integer> builder = ImmutableMap.<String, Integer>builder();
builder.putAll(map1);
map2.forEach((k, v) -> {if (!map1.containsKey(k)) builder.put(k, v);});
ImmutableMap<String, Integer> map3 = builder.build();
Run Code Online (Sandbox Code Playgroud)
有关两个映射中存在的值需要与映射函数组合的情况,另请参阅使用Java 8合并两个映射.
Xae*_*ess 31
如果您不需要为可变性最终的地图,还有番石榴的 ImmutableMap,其Builder和putAll方法这,相比于Java的Map接口方法,可以链接.
使用示例:
Map<String, Integer> mergeMyTwoMaps(Map<String, Integer> map1, Map<String, Integer> map2) {
return ImmutableMap.<String, Integer>builder()
.putAll(map1)
.putAll(map2)
.build();
}
Run Code Online (Sandbox Code Playgroud)
当然,这个方法可以更通用,使用varargs和循环putAll Maps来自参数等但我想展示一个概念.
此外,ImmutableMap它Builder有几个限制(或可能是功能?):
NullPointerException- 如果map中的任何键或值为null)IllegalArgumentException如果添加了重复键,则抛出).hvg*_*des 26
HashMap有一个putAll方法.
http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
Zhe*_*lov 11
用于组合两个可能共享公共密钥的映射的通用解决方案:
到位:
public static <K, V> void mergeInPlace(Map<K, V> map1, Map<K, V> map2,
BinaryOperator<V> combiner) {
map2.forEach((k, v) -> map1.merge(k, v, combiner::apply));
}
Run Code Online (Sandbox Code Playgroud)
返回新地图:
public static <K, V> Map<K, V> merge(Map<K, V> map1, Map<K, V> map2,
BinaryOperator<V> combiner) {
Map<K, V> map3 = new HashMap<>(map1);
map2.forEach((k, v) -> map3.merge(k, v, combiner::apply));
return map3;
}
Run Code Online (Sandbox Code Playgroud)
很晚了,但让我分享我在遇到同样问题时所做的事情。
Map<String, List<String>> map1 = new HashMap<>();
map1.put("India", Arrays.asList("Virat", "Mahi", "Rohit"));
map1.put("NZ", Arrays.asList("P1","P2","P3"));
Map<String, List<String>> map2 = new HashMap<>();
map2.put("India", Arrays.asList("Virat", "Mahi", "Rohit"));
map2.put("NZ", Arrays.asList("P1","P2","P4"));
Map<String, List<String>> collect4 = Stream.of(map1, map2)
.flatMap(map -> map.entrySet().stream())
.collect(
Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(strings, strings2) -> {
List<String> newList = new ArrayList<>();
newList.addAll(strings);
newList.addAll(strings2);
return newList;
}
)
);
collect4.forEach((s, strings) -> System.out.println(s+"->"+strings));
Run Code Online (Sandbox Code Playgroud)
它给出了以下输出
NZ->[P1, P2, P3, P1, P2, P4]
India->[Virat, Mahi, Rohit, Virat, Mahi, Rohit]
Run Code Online (Sandbox Code Playgroud)