web-dev-qa-db-ja.com

重複したキーがHashMapに入れられるとどうなりますか?

同じキーをHashMapputメソッドに複数回渡すと、元の値はどうなりますか?そして、その値が繰り返されたとしてもどうでしょうか。これに関する文書は見つかりませんでした。

ケース1:キーの上書き値

Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","not one");
mymap.put("1","surely not one");
System.out.println(mymap.get("1"));

surely not oneを受け取ります。

ケース2:重複値

Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","not one");
mymap.put("1","surely not one");
// The following line was added:
mymap.put("1","one");
System.out.println(mymap.get("1"));

oneを得ます。

しかし、他の値はどうなりますか?私は学生に基本を教えていました、そして私はこれを頼まれました。 Mapは、最後の値が参照されるバケットのようなものです(ただし、メモリ内にありますか)。

253
boodieye

定義上、putコマンドは、マップ内の指定されたキーに関連付けられている以前の値を置き換えます(概念的には、プリミティブ型の配列インデックス操作のようなものです)。

マップは単にその値への参照を削除します。そのオブジェクトへの参照が他に何も保持されていない場合、そのオブジェクトはガベージコレクションの対象になります。さらに、Javaは指定されたキーに関連付けられた以前の値(存在しない場合はnull)を返すため、存在したものを特定し、必要に応じて参照を維持できます。

ここでより多くの情報: HashMap Doc

289
jheddings

答えは Map#put(K、V) のJavadocにあります(実際には何かを返します)。

public V put(K key,
             V value)

指定された値をこのマップ内の指定されたキーに関連付けます(オプションの操作)。マップが以前にこのキーのマッピングを含んでいた場合は、古い値が指定された値に置き換えられます。 (マップmは、 m.containsKey(k)kを返す場合に限り、キーtrueへのマッピングを含むと言われます。)

パラメータ:
key - 指定された値が関連付けられるキー。
value - 指定されたキーに関連付けられる値.

戻り値:
指定されたキーに関連付けられた以前の値、またはnullのマッピングがなかった場合はkey。 (実装がnull値をサポートする場合、nullの戻り値は、マップが以前にkeyを指定されたnullに関連付けたことを示すこともできます。)

そのため、mymap.put("1", "a string")を呼び出すときに戻り値を代入しないと、単に参照されなくなり、ガベージコレクションの対象になります。

70
Pascal Thivent

キーの以前の値はドロップされ、新しい値に置き換えられます。

キーに与えられたすべての値を保持したい場合は、次のように実装することを検討してください。

import org.Apache.commons.collections.MultiHashMap;
import Java.util.Set;
import Java.util.Map;
import Java.util.Iterator;
import Java.util.List;
public class MultiMapExample {

   public static void main(String[] args) {
      MultiHashMap mp=new MultiHashMap();
      mp.put("a", 10);
      mp.put("a", 11);
      mp.put("a", 12);
      mp.put("b", 13);
      mp.put("c", 14);
      mp.put("e", 15);
      List list = null;

      Set set = mp.entrySet();
      Iterator i = set.iterator();
      while(i.hasNext()) {
         Map.Entry me = (Map.Entry)i.next();
         list=(List)mp.get(me.getKey());

         for(int j=0;j<list.size();j++)
         {
          System.out.println(me.getKey()+": value :"+list.get(j));
         }
      }
   }
}
18
kamlesh0606

これはキー/値機能であり、実際の値を取得したいときに入力されたキーに属する値があるため、複数の値に対して重複キーを持つことはできません。
あなたの例であなたが "1"の値を取得したいときはどれですか?
これがすべての値に固有のキーを持つ理由ですが、Java標準のlibによるトリックを持つことができます。

import Java.util.ArrayList;
import Java.util.HashMap;
import Java.util.Map;

public class DuplicateMap<K, V> {

    private Map<K, ArrayList<V>> m = new HashMap<>();

    public void put(K k, V v) {
        if (m.containsKey(k)) {
            m.get(k).add(v);
        } else {
            ArrayList<V> arr = new ArrayList<>();
            arr.add(v);
            m.put(k, arr);
        }
    }

     public ArrayList<V> get(K k) {
        return m.get(k);
    }

    public V get(K k, int index) {
        return m.get(k).size()-1 < index ? null : m.get(k).get(index);
    }
}


そして、あなたはこのようにそれを使うことができます:

    public static void main(String[] args) {
    DuplicateMap<String,String> dm=new DuplicateMap<>();
    dm.put("1", "one");
    dm.put("1", "not one");
    dm.put("1", "surely not one");
    System.out.println(dm.get("1"));
    System.out.println(dm.get("1",1));
    System.out.println(dm.get("1", 5));
}

と印刷の結果は次のとおりです。

[one, not one, surely not one]
not one
null
17
java acm

このマップ内の指定されたキーに指定された値を関連付けます。マップが以前にキーのマッピングを含んでいた場合、古い値が置き換えられます

12
Diego Alejandro

地図がバケツのようなものであるかどうかについてのあなたの質問に:いいえ。

これはname=valueの組を含むリストのようなものですが、nameはStringである必要はありません(ただし可能です)。

要素を取得するには、get() - メソッドにキーを渡します。これにより、割り当てられたオブジェクトが返されます。

また、ハッシュマップは、getメソッドを使ってオブジェクトを取得しようとしている場合、実際のオブジェクトと指定したオブジェクトを比較しないことを意味します。リストを反復処理し、現在の要素に指定したキーをcompare()する必要があります。

これは非効率的です。代わりに、あなたのオブジェクトが何から構成されていようとも、それは両方のオブジェクトからいわゆるハッシュコードを計算し、それらを比較します。 2つの(場合によっては非常に複雑な)オブジェクト全体ではなく、2つのintを比較する方が簡単です。ハッシュコードは、事前定義された長さ(int)を持つ要約のように想像できます。したがって、ハッシュコードは一意ではなく、衝突があります。ハッシュコードの規則は、私がリンクを挿入した文書にあります。

これについてもっと知りたい場合は、 javapractices.comtechnofundoの記事を見てみたいと思うかもしれません。 .com

よろしく

4
Atmocreations

それはそれぞれのキーのマップの既存の値を置き換えます。そして同じ名前のキーが存在しない場合は、与えられた値でキーを作成します。例えば:

Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","two");

OUTPUTkey = "1"、value = "two"

そのため、以前の値は上書きされます。

3
Bishal Jaiswal

私はいつも使っていました:

HashMap<String, ArrayList<String>> hashy = new HashMap<String, ArrayList<String>>();

ひとつの識別キーに複数のことを適用したい場合.

public void MultiHash(){
    HashMap<String, ArrayList<String>> hashy = new HashMap<String, ArrayList<String>>();
    String key = "Your key";

    ArrayList<String> yourarraylist = hashy.get(key);

    for(String valuessaved2key : yourarraylist){
        System.out.println(valuessaved2key);
    }

}

あなたはいつでもこのようなことをして自分自身を迷路にすることができます!

public void LOOK_AT_ALL_THESE_HASHMAPS(){
    HashMap<String, HashMap<String, HashMap<String, HashMap<String, String>>>> theultimatehashmap = new HashMap <String, HashMap<String, HashMap<String, HashMap<String, String>>>>();
    String ballsdeep_into_the_hashmap = theultimatehashmap.get("firststring").get("secondstring").get("thirdstring").get("forthstring");
}
3
sheepiiHD

はい、これは値を持つすべての1つのキーが最後に追加された値で上書きされることを意味します。

たとえあなたがループで表示しようとしていても、それはまた同じキーを持つ一つのキーと値のみを表示します。

1
ajaynakrani

ところで、このキーが存在しない場合にのみ置くといったセマンティクスが必要な場合は。あなたはputIfAbsent()関数と一緒にconcurrentHashMapを使うことができます。これをチェックしてください。

https://docs.Oracle.com/javase/7/docs/api/Java/util/concurrent/ConcurrentHashMap.html#put(K、%20V)

concurrentHashMapは "ロックストライピング "スループットを向上させるメカニズム。

1
BufBills

JDKからのマップは重複したキーの下にデータを格納するためのものではありません。

  • せいぜい新しい値が前の値を上書きします。

  • 悪いシナリオは例外です(例:ストリームとして集めようとしたとき):

重複なし

Stream.of("one").collect(Collectors.toMap(x -> x, x -> x))

OK。あなたは得るでしょう:$ 2 ==> {one = one}

複製ストリーム

Stream.of("one", "not one", "surely not one").collect(Collectors.toMap(x -> 1, x -> x))

例外Java.lang.IllegalStateException:重複キー1(1ではなく1の値のマージを試みました) Collectors.duplicateKeyExceptionで(Collectors.Java:133) Collectors.lambda $ uniqKeysMapAccumulator $ 1で(Collectors.Java:180)|でReduceOps $ 3ReducingSink.accept(ReduceOps.Java:169)|お問い合わせSpliteratorsで$ ArraySpliterator.forEachRemaining(Spliterators.Java:948)| AbstractPipeline.copyIntoで(AbstractPipeline.Java:484)| AbstractPipeline.wrapAndCopyInto(AbstractPipeline.Java:474)でReduceOps $ ReduceOp.evaluateSequential(ReduceOps.Java:913)| AbstractPipeline.evaluateで(AbstractPipeline.Java:234)| ReferencePipeline.collectで(ReferencePipeline.Java:578)|で(#4:1)

重複したキーを処理するには - 他のパッケージを使用してください。例: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Multimap.html

重複したキーを扱う実装は他にもたくさんあります。それらはウェブに必要です(例:重複したクッキーキー、HTTPヘッダは同じフィールドを持つことができます、など)。

がんばろう! :)

1
Witold Kaczurba