webentwicklung-frage-antwort-db.com.de

Was passiert, wenn ein doppelter Schlüssel in eine HashMap eingefügt wird?

Wenn ich denselben Schlüssel mehrmals an die HashMap-Methode von put übergeben, was passiert dann mit dem ursprünglichen Wert? Und was ist, wenn sich der Wert wiederholt? Ich habe dazu keine Dokumentation gefunden.

Fall 1: Werte für einen Schlüssel überschrieben

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"));

Wir bekommen surely not one.

Fall 2: Doppelter Wert

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"));

Wir bekommen one.

Was passiert aber mit den anderen Werten? Ich unterrichtete einen Studenten mit Grundlagen und wurde danach gefragt. Ist die Variable Map ein Bereich, in dem der letzte Wert referenziert wird (aber im Speicher)?

244
boodieye

Per Definition ersetzt der Befehl put den vorherigen Wert, der dem angegebenen Schlüssel in der Map zugeordnet ist (konzeptionell wie eine Array-Indexierungsoperation für primitive Typen).

Die Karte löscht einfach ihren Verweis auf den Wert. Wenn nichts anderes einen Verweis auf das Objekt enthält, kann dieses Objekt für die Garbage Collection verwendet werden. Darüber hinaus gibt Java einen beliebigen früheren Wert zurück, der dem angegebenen Schlüssel zugeordnet ist (oder null, falls keiner vorhanden ist), sodass Sie feststellen können, was dort vorhanden war, und ggf. eine Referenz beibehalten.

Weitere Informationen hier: HashMap Doc

281
jheddings

Sie finden Ihre Antwort im Javadoc von Map # put (K, V) (was tatsächlich etwas zurückgibt):

public V put(K key,
             V value)

Ordnet den angegebenen Wert dem angegebenen Schlüssel in dieser Map zu (optionale Bedienung). Wenn die Karte enthielt zuvor ein Mapping für Bei diesem Schlüssel wird der alte Wert durch .__ ersetzt. der angegebene Wert. (Eine Karte m soll Enthalten, die eine Zuordnung für einen Schlüssel k enthält, wenn Und nur wenn m.containsKey(k) würde Return true. Sein.)

Parameter:
key - Schlüssel, mit dem der angegebene Wert verknüpft werden soll.
value - Wert, der dem angegebenen Schlüssel zugeordnet werden soll. 

Kehrt zurück:
vorheriger Wert, der dem angegebenen Schlüssel zugeordnet ist, oder null, wenn kein .__ vorhanden war. Zuordnung für key. (Ein null return kann auch angeben, dass die Map zuvor der angegebenen nullkey zugeordnet wurde, wenn die Implementierung null-Werte unterstützt.)

Wenn Sie also beim Aufruf von mymap.put("1", "a string") den zurückgegebenen Wert nicht zuweisen, wird der Wert nicht mehr referenziert und ist somit für die Garbage Collection geeignet.

70
Pascal Thivent

Der vorherige Wert für den Schlüssel wird verworfen und durch den neuen ersetzt.

Wenn Sie alle Werte beibehalten möchten, die für einen Schlüssel angegeben sind, können Sie etwa Folgendes implementieren:

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

es ist die Key/Value-Funktion, und Sie können für mehrere Werte keinen Duplikatschlüssel haben, da Sie den tatsächlichen Wert abrufen möchten, zu dem einer der Werte gehört
in Ihrem Beispiel, wenn Sie den Wert "1" erhalten möchten. Welches ist es?!
das ist Gründe, einen eindeutigen Schlüssel für jeden Wert zu haben, aber Sie könnten einen Trick mit der Java-Standardlib haben:

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);
    }
}


und Sie könnten es auf diese Weise verwenden:

    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));
}

und Ergebnis der Drucke sind:

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

Ordnet den angegebenen Wert dem angegebenen Schlüssel in dieser Zuordnung zu. Wenn die Zuordnung zuvor eine Zuordnung für den Schlüssel enthielt, wird der alte Wert ersetzt.

11
Diego Alejandro

Zu deiner Frage, ob die Karte wie ein Eimer war: Nein.

Es ist wie eine Liste mit name=value Paaren, wohingegen name kein String sein muss (es kann jedoch auch).

Um ein Element zu erhalten, übergeben Sie Ihren Schlüssel an die get () - Methode, die Ihnen das zugewiesene Objekt zurückgibt.

Und eine Hash - Map bedeutet, dass wenn Sie versuchen, Ihr Objekt mit der get-Methode abzurufen, das reale Objekt nicht mit dem von Ihnen angegebenen Objekt verglichen wird, da es seine Liste durchlaufen und vergleichen muss () der Schlüssel, den Sie mit dem aktuellen Element erhalten haben.

Dies wäre ineffizient. Unabhängig davon, woraus Ihr Objekt besteht, berechnet es aus beiden Objekten einen sogenannten Hashcode und vergleicht diesen. Es ist einfacher, zwei ints anstelle von zwei vollständigen (möglicherweise sehr komplexen) Objekten zu vergleichen. Sie können sich den Hashcode wie eine Zusammenfassung mit einer vordefinierten Länge (int) vorstellen. Daher ist er nicht eindeutig und hat Kollisionen. Die Regeln für den Hashcode finden Sie in der Dokumentation, in die ich den Link eingefügt habe.

Wenn Sie mehr darüber erfahren möchten, werfen Sie einen Blick auf die Artikel zu javapractices.com und technofundo.com

grüße

4
Atmocreations

Ich habe immer gebraucht:

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

wenn ich mehrere Dinge auf einen Identifikationsschlüssel anwenden wollte. 

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);
    }

}

sie könnten immer so etwas tun und sich ein Labyrinth schaffen!

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

Ja, das bedeutet, dass alle 1 Schlüssel mit Wert mit dem letzten Mehrwert überschrieben werden. Hier fügen Sie "sicher nicht eins" hinzu, sodass nur "sicher nicht eins" angezeigt wird.

Selbst wenn Sie versuchen, mit einer Schleife anzuzeigen, werden nur ein Schlüssel und ein Wert mit demselben Schlüssel angezeigt.

1
ajaynakrani

Übrigens, wenn Sie etwas Semantik wollen, zB nur setzen, wenn dieser Schlüssel nicht vorhanden ist. Sie können concurrentHashMap mit putIfAbsent() function ..__ verwenden. Überprüfen Sie Folgendes:

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

concurrentHashMap ist mit hoher Leistung Thread-sicher, da der Mechanismus "lock striping" verwendet, um den Durchsatz zu verbessern. 

1
BufBills

Karten von JDK sind nicht zum Speichern von Daten unter duplizierten Schlüsseln gedacht.

  • Bestenfalls überschreibt ein neuer Wert die vorherigen.

  • Schlimmeres Szenario ist die Ausnahme (z. B. wenn Sie versuchen, es als Stream zu sammeln):

Keine Duplikate:

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

Okay. Sie erhalten: $ 2 ==> {one = one}

Duplizierter Stream:

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

Ausnahme Java.lang.IllegalStateException: Doppelter Schlüssel 1 (versucht, Werte eins und nicht eins zusammenzuführen) | at Collectors.duplicateKeyException (Collectors.Java:133) | at Collectors.lambda $ uniqKeysMapAccumulator $ 1 (Collectors.Java:180) | at ReduceOps $ 3ReducingSink.accept (ReduceOps.Java:169) | at Spliterators $ ArraySpliterator.forEachRemaining (Spliterators.Java:948) | at AbstractPipeline.copyInto (AbstractPipeline.Java:484) | at AbstractPipeline.wrapAndCopyInto (AbstractPipeline.Java:474) | at ReduceOps $ ReduceOp.evaluateSequential (ReduceOps.Java:913) | at AbstractPipeline.evaluate (AbstractPipeline.Java:234) | at ReferencePipeline.collect (ReferencePipeline.Java:578) | um (# 4: 1)

Verwenden Sie zum Behandeln duplizierter Schlüssel ein anderes Paket, z. B .: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Multimap.html

Es gibt viele andere Implementierungen, die sich mit doppelten Schlüsseln befassen. Diese werden für das Web benötigt (z. B. doppelte Cookie-Schlüssel, HTTP-Header können dieselben Felder haben, ...)

Viel Glück! :)

1
Witold Kaczurba

Es ersetzt den vorhandenen Wert in der Karte für den jeweiligen Schlüssel. Wenn kein Schlüssel mit demselben Namen vorhanden ist, erstellt er einen Schlüssel mit dem angegebenen Wert .

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

AUSGABE key = "1", value = "two"

Der vorherige Wert wird also überschrieben.

0
Bishal Jaiswal