web-dev-qa-db-fra.com

Différence entre replace et put pour HashMap

Je veux créer un histogramme en utilisant un HashMap, la clé doit être le délai, la valeur le nombre de fois où ce délai se produit. Je doute d'utiliser la fonction HashMapreplace ou HashMapput si un retard existant a une nouvelle occurrence. 

Je l'ai fait de cette façon 

int delay = (int) (loopcount-packetServed.getArrivalTime());
if(histogramType1.containsKey(delay))
{
    histogramType1.replace(delay, histogramType1.get(delay)+1);   
}
else
{
    histogramType1.put(delay, 1);
}

Est-ce correct? ou devrais-je utiliser deux fois la fonction put?

11
StudentX

Il n'y a absolument aucune différence entre put et replace lorsqu'il existe un mappage en cours pour la clé recherchée. De replace :

Remplace l'entrée de la clé spécifiée uniquement si elle est actuellement mappée sur une valeur.

Cela signifie que s'il existe déjà un mappage pour la clé donnée, put et replace mettront à jour la mappe de la même manière. Les deux renverront également la valeur précédente associée à la clé. Cependant, s'il n'y a pas de mappage pour cette clé, alors replace sera un no-op (ne fera rien) alors que put mettra toujours à jour la carte.


À partir de Java 8, notez que vous pouvez simplement utiliser

histogramType1.merge(delay, 1, Integer::sum);

Cela prendra soin de toutes les conditions. De merge :

Si la clé spécifiée n'est pas déjà associée à une valeur ou est associée à null, associez-la à la valeur non nulle donnée. Sinon, remplace la valeur associée par les résultats de la fonction de remappage donnée ou est supprimée si le résultat est null.

Dans ce cas, nous créons l'entrée delay -> 1 si l'entrée n'existait pas. S'il existait, il est mis à jour en incrémentant la valeur de 1.

20
Tunaki

Dans votre cas, puisque vous avez d’abord vérifié si la valeur est contenue dans la carte, utiliser put ou replace conduit au même résultat.

Vous pouvez utiliser l’un ou l’autre, en fonction de ce qui vous est le plus lisible.

2
Jean Logeart

Si vous regardez les sources, vous pouvez voir ce qui suit (ceci provient de la mise à jour 11 mais n'a probablement pas beaucoup changé):

remplace :

if ((e = getNode(hash(key), key)) != null) {
    V oldValue = e.value;
    e.value = value;
    afterNodeAccess(e);
    return oldValue;
}    

put (méthode interne putVal):

//some code before this to find the node e (similar to getNode(hash(key)))
if (e != null) { // existing mapping for key
   V oldValue = e.value;
   if (!onlyIfAbsent || oldValue == null)  //onlyIfAbsent is false here
     e.value = value;
   afterNodeAccess(e);
   return oldValue;
}

Comme vous pouvez le constater, les parties pertinentes du code font essentiellement la même chose puisque onlyIfAbsent est false pour put et remplacera donc toujours la valeur.

1
Thomas

Vous pouvez vérifier le comportement décrit par les autres, avec ceci:

public class Main {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.replace("a", "1");
        System.out.println(map.get("a"));

        map.put("a", "1");
        System.out.println(map.get("a"));

        map.replace("a", "2");
        System.out.println(map.get("a"));
    }
}
0
EdgeCase