Java 如何组合包含相同类型的两个 HashMap 对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4299728/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I combine two HashMap objects containing the same types?
提问by Mavin
I have two HashMap
objects defined like so:
我有两个HashMap
像这样定义的对象:
HashMap<String, Integer> map1 = new HashMap<String, Integer>();
HashMap<String, Integer> map2 = new HashMap<String, Integer>();
I also have a third HashMap
object:
我还有第三个HashMap
对象:
HashMap<String, Integer> map3;
How can I merge map1
and map2
together into map3
?
我该如何合并map1
,并map2
汇集成map3
?
回答by fastcodejava
You could use Collection.addAll()for other types, e.g. List
, Set
, etc. For Map
, you can use putAll
.
你可以使用Collection.addAll()对于其他类型,例如List
,Set
等等。Map
你可以使用putAll
。
回答by hvgotcodes
HashMap has a putAll
method.
HashMap 有一个putAll
方法。
http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
回答by a_horse_with_no_name
map3 = new HashMap<>();
map3.putAll(map1);
map3.putAll(map2);
回答by Xaerxess
If you don't need mutability for your final map, there is Guava'sImmutableMap
with its Builder
and putAll
methodwhich, in contrast to Java's Map
interface method, can be chained.
如果您不需要为可变性最终的地图,还有番石榴的ImmutableMap
,其Builder
和putAll
方法这,相比于Java的Map
接口方法,可以链接。
Example of use:
使用示例:
Map<String, Integer> mergeMyTwoMaps(Map<String, Integer> map1, Map<String, Integer> map2) {
return ImmutableMap.<String, Integer>builder()
.putAll(map1)
.putAll(map2)
.build();
}
Of course, this method can be more generic, use varargs and loop to putAll
Maps
from arguments etc. but I wanted to show a concept.
当然,这个方法可以更通用,使用 varargs 和 loop to putAll
Maps
from arguments 等,但我想展示一个概念。
Also, ImmutableMap
and its Builder
have few limitations (or maybe features?):
此外,ImmutableMap
它Builder
几乎没有限制(或者可能是功能?):
- they are null hostile (throw
NullPointerException
- if any key or value in map is null) - Builder don't accept duplicate keys (throws
IllegalArgumentException
if duplicate keys were added).
- 它们是空敌对的(抛出
NullPointerException
- 如果地图中的任何键或值为空) - Builder 不接受重复键(
IllegalArgumentException
如果添加了重复键则抛出)。
回答by Jeffrey Bosboom
If you know you don't have duplicate keys, or you want values in map2
to overwrite values from map1
for duplicate keys, you can just write
如果你知道你没有重复的键,或者你想要值map2
覆盖map1
重复键的值,你可以写
map3 = new HashMap<>(map1);
map3.putAll(map2);
If you need more control over how values are combined, you can use Map.merge
, added in Java 8, which uses a user-provided BiFunction
to merge values for duplicate keys. merge
operates on individual keys and values, so you'll need to use a loop or Map.forEach
. Here we concatenate strings for duplicate keys:
如果您需要更多地控制值的组合方式,您可以使用Map.merge
Java 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));
If you know you don't have duplicate keys and want to enforce it, you can use a merge function that throws an AssertionError
:
如果你知道你没有重复的键并且想要强制执行它,你可以使用一个合并函数来抛出一个AssertionError
:
map2.forEach((k, v) ->
map3.merge(k, v, (v1, v2) ->
{throw new AssertionError("duplicate values for key: "+k);}));
Taking a step back from this specific question, the Java 8 streams library provides toMap
and groupingBy
Collectors. If you're repeatedly merging maps in a loop, you may be able to restructure your computation to use streams, which can both clarify your code and enable easy parallelism using a parallel stream and concurrent collector.
从这个特定问题退后一步,Java 8 流库提供了toMap
和groupingBy
Collectors。如果您在循环中反复合并映射,您可能能够重构您的计算以使用流,这既可以澄清您的代码,又可以使用并行流和并发收集器轻松实现并行化。
回答by Vadzim
Java 8 alternative one-liner for merging two maps:
用于合并两个地图的 Java 8 替代单线:
defaultMap.forEach((k, v) -> destMap.putIfAbsent(k, v));
The same with method reference:
与方法参考相同:
defaultMap.forEach(destMap::putIfAbsent);
Or idemponent for original maps solution with third map:
或具有第三张地图的原始地图解决方案的幂次:
Map<String, Integer> map3 = new HashMap<String, Integer>(map2);
map1.forEach(map3::putIfAbsent);
And here is a way to merge two maps into fast immutable one with Guavathat does least possible intermediate copy operations:
这是一种使用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();
See also Merge two maps with Java 8for cases when values present in both maps need to be combined with mapping function.
另请参阅将两个映射与 Java 8 合并以了解两个映射中存在的值需要与映射函数组合的情况。
回答by Vitalii Fedorenko
One-liner using Java 8 Stream API:
单线使用 Java 8 Stream API:
map3 = Stream.of(map1, map2).flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue))
Among the benefits of this method is ability to pass a merge function, which will deal with values that have the same key, for example:
此方法的好处之一是能够传递合并函数,该函数将处理具有相同键的值,例如:
map3 = Stream.of(map1, map2).flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, Math::max))
回答by Ashish Shetkar
you can use - addAll method
您可以使用 - addAll 方法
http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
But there is always this issue that - if your two hash maps have any key same - then it will override the value of the key from first hash map with the value of the key from second hash map.
但是总是存在这个问题——如果你的两个散列映射有任何相同的键——那么它将用第二个散列映射中的键值覆盖第一个散列映射中的键值。
For being on safer side - change the key values - you can use prefix or suffix on the keys - ( different prefix/suffix for first hash map and different prefix/suffix for second hash map )
为了更安全 - 更改键值 - 您可以在键上使用前缀或后缀 - (第一个哈希映射使用不同的前缀/后缀,第二个哈希映射使用不同的前缀/后缀)
回答by ZhekaKozlov
Generic solution for combining two maps which can possibly share common keys:
组合两个可能共享公共密钥的映射的通用解决方案:
In-place:
到位:
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));
}
Returning a new map:
返回一张新地图:
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;
}
回答by Thomas Decaux
A small snippet I use very often to create map from other maps:
我经常使用的一个小片段从其他地图创建地图:
static public <K, V> Map<K, V> merge(Map<K, V>... args) {
final Map<K, V> buffer = new HashMap<>();
for (Map m : args) {
buffer.putAll(m);
}
return buffer;
}