あるJavaハッシュマップコンテンツにAllを配置するが、既存のキーと値を置き換えない方法は?


83

すべてのキーと値を1つのAハッシュマップから別のBにコピーする必要がありますが、既存のキーと値を置き換える必要はありません。

それを行うための最良の方法は何ですか?

代わりに、keySetを繰り返して、存在するかどうかを確認することを考えていました。

Map temp = new HashMap(); // generic later
temp.putAll(Amap);
A.clear();
A.putAll(Bmap);
A.putAll(temp);

回答:


108

一時的なものを作成しても構わMapないと思っているようですので、次のようにします。

Map tmp = new HashMap(patch);
tmp.keySet().removeAll(target.keySet());
target.putAll(tmp);

これpatchが、マップに追加するtargetマップです。

Louis Wassermanのおかげで、Java8の新しいメソッドを利用するバージョンを次に示します。

patch.forEach(target::putIfAbsent);

この場合、removeAllとにかくオーバーライドされるため、実行する必要はありません。
ゴンゾ牧師2011

@ゴンゾ牧師:何で上書きされたの?
エリクソン2011

@luksmirいいえ、保存する必要のある既存のエントリが削除されます。
エリクソン2014

こんにちは!mapWithValues.putAll(mapWithAnotherValues)が機能しないのはなぜですか?
betomoretti 2015年

15
@ericksonはるかにコンパクトなJava8バージョン:patch.forEach(target::putIfAbsent)
Louis Wasserman 2016年

15

使用グアバ地図あなたはそれがより多くのあなたが達成しようとしているものを明確にメソッドシグネチャで、単一の行でそれを行うことができます2つのマップの違いを計算するためにクラスのユーティリティメソッドを:

public static void main(final String[] args) {
    // Create some maps
    final Map<Integer, String> map1 = new HashMap<Integer, String>();
    map1.put(1, "Hello");
    map1.put(2, "There");
    final Map<Integer, String> map2 = new HashMap<Integer, String>();
    map2.put(2, "There");
    map2.put(3, "is");
    map2.put(4, "a");
    map2.put(5, "bird");

    // Add everything in map1 not in map2 to map2
    map2.putAll(Maps.difference(map1, map2).entriesOnlyOnLeft());
}

8

繰り返して追加するだけです:

for(Map.Entry e : a.entrySet())
  if(!b.containsKey(e.getKey())
    b.put(e.getKey(), e.getValue());

編集して追加:

に変更を加えることができる場合は、次のこともできます。

a.putAll(b)

そして、あなたが必要なものを正確に持っているでしょう。(すべてのエントリではbとのすべてのエントリaに含まれていないことb


1.)をentrySet()返しますSet<Map.Entry>。2.)方法がないcontains(...)ためjava.util.Map
ファビアンバーニー

より賢い方法はありませんか?コレクションユーティリティなどのように?私はどこでもすべてのforループが嫌いです。
ラパドゥラ2011

1
@AntonioP:どこにでもあるすべてのforループ?forループが1つあり、それは可能な限り簡単です。
ゴンゾ牧師2011

+1すると、マップがrawタイプで使用されていない場合にのみ機能すると思います。Map.Entryに少し戸惑いました:
Fabian Barney

@Reverend Gonzo、ああ、コードの他の場所。:) .putAllは、?の既存のキーと値を置き換えません。この感覚で行くと、それは最も簡単な方法のように思えます。
ラパドゥラ2011

5

@ericksonのソリューションでマップの順序を変更すると、1行で作成できます。

mapWithNotSoImportantValues.putAll( mapWithImportantValues );

この場合、mapWithNotSoImportantValuesの値を、同じキーを持つmapWithImportantValuesの値に置き換えます。


2
public class MyMap {

public static void main(String[] args) {

    Map<String, String> map1 = new HashMap<String, String>();
    map1.put("key1", "value1");
    map1.put("key2", "value2");
    map1.put("key3", "value3");
    map1.put(null, null);

    Map<String, String> map2 = new HashMap<String, String>();
    map2.put("key4", "value4");
    map2.put("key5", "value5");
    map2.put("key6", "value6");
    map2.put("key3", "replaced-value-of-key3-in-map2");
    // used only if map1 can be changes/updates with the same keys present in map2.
    map1.putAll(map2);

    // use below if you are not supposed to modify the map1.
    for (Map.Entry e : map2.entrySet())
        if (!map1.containsKey(e.getKey()))
            map1.put(e.getKey().toString(), e.getValue().toString());
    System.out.println(map1);
}}

2

Java 8には、要件を満たすためのこのAPIメソッドがあります。

map.putIfAbsent(key, value)

指定されたキーがまだ値に関連付けられていない(またはnullにマップされている)場合は、指定された値に関連付けてnullを返します。それ以外の場合は、現在の値を返します。


1
putAllIfAbsentを作成できますか?それだけが必要 ?
user1735921 2018

0

他の人が言っているように、あなたは使うことができますputIfAbsent。挿入するマップの各エントリを繰り返し処理し、元のマップでこのメソッドを呼び出します。

mapToInsert.forEach(originalMap::putIfAbsent);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.