Supposons que nous ayons un HashMap<String, Integer>
en Java.
Comment mettre à jour (incrémenter) la valeur entière de la clé de chaîne pour chaque existence de la chaîne que je trouve?
On pourrait retirer et rentrer la paire, mais les frais généraux seraient une préoccupation.
Une autre façon serait de simplement mettre la nouvelle paire et l'ancienne serait remplacée.
Dans ce dernier cas, que se passe-t-il en cas de collision de hashcode avec une nouvelle clé que j'essaie d'insérer? Le comportement correct d'une table de hachage consiste à lui attribuer un emplacement différent ou à en créer une liste dans le compartiment actuel.
getOrDefault
, par exemple:map.put(key, count.getOrDefault(key, 0) + 1);
Java 8 voies:
Vous pouvez utiliser la
computeIfPresent
méthode et lui fournir une fonction de mappage, qui sera appelée pour calculer une nouvelle valeur en fonction de celle existante.Par exemple,
Alternativement, vous pouvez utiliser la
merge
méthode, où 1 est la valeur par défaut et la fonction incrémente la valeur existante de 1:De plus, il y a un tas d'autres méthodes utiles, telles que
putIfAbsent
,getOrDefault
,forEach
, etc.la source
null
(disonswords.put("hello", null);
), le résultat n'est toujoursnull
pas1
comme je m'y attendais.compute()
place, il gérera également lesnull
valeurs..merge
est ma solution avecInteger::sum
.La méthode
put
va remplacer la valeur d'une clé existante et créer si n'existe pas.la source
nullPointer Exception
.null + 1
car cela va essayer de déballer lenull
dans un entier pour faire l'incrément.La manière simplifiée de Java 8 :
Cela utilise la méthode de HashMap qui récupère la valeur d'une clé, mais si la clé ne peut pas être récupérée, elle renvoie la valeur par défaut spécifiée (dans ce cas, un «0»).
Ceci est pris en charge dans le noyau Java: HashMap <K, V> getOrDefault (clé d'objet, V defaultValue)
la source
Remplacez
Integer
parAtomicInteger
et appelez l'une des méthodesincrementAndGet
/getAndIncrement
dessus.Une alternative consiste à envelopper un
int
dans votre propreMutableInteger
classe qui a uneincrement()
méthode, vous n'avez encore qu'un problème de threadsafety à résoudre.la source
MutableInteger
est meilleure, comme lesAtomicInteger
utilisationsvolatile
, ce qui a des frais généraux. J'utiliseraisint[1]
plutôtMutableInteger
.Solution en une ligne:
la source
@ La solution de Matthew est la plus simple et fonctionnera assez bien dans la plupart des cas.
Si vous avez besoin de hautes performances, AtomicInteger est une meilleure solution ala @BalusC.
Cependant, une solution plus rapide (à condition que la sécurité des threads ne soit pas un problème) consiste à utiliser TObjectIntHashMap qui fournit une méthode d'incrémentation (clé) et utilise des primitives et moins d'objets que la création d'AtomicIntegers. par exemple
la source
Vous pouvez incrémenter comme ci-dessous mais vous devez vérifier son existence afin qu'une NullPointerException ne soit pas levée
la source
Le hachage existe-t-il (avec 0 comme valeur) ou est-il "mis" sur la carte au premier incrément? S'il est "mis" sur le premier incrément, le code devrait ressembler à:
la source
Il est peut-être un peu tard mais voici mes deux cents.
Si vous utilisez Java 8, vous pouvez utiliser la méthode computeIfPresent . Si la valeur de la clé spécifiée est présente et non nulle, elle tente de calculer un nouveau mappage en fonction de la clé et de sa valeur mappée actuelle.
Nous pouvons également utiliser une autre méthode putIfAbsent pour mettre une clé. Si la clé spécifiée n'est pas déjà associée à une valeur (ou est mappée à null), cette méthode l'associe à la valeur donnée et renvoie null, sinon renvoie la valeur actuelle.
Dans le cas où la carte est partagée entre plusieurs threads, nous pouvons utiliser
ConcurrentHashMap
et AtomicInteger . Du doc:Nous pouvons les utiliser comme indiqué:
Un point à observer est que nous invoquons
get
pour obtenir la valeur de la cléB
, puis invoquonsincrementAndGet()
sa valeur qui est bien sûrAtomicInteger
. Nous pouvons l'optimiser car la méthodeputIfAbsent
renvoie la valeur de la clé si elle est déjà présente:D'un autre côté, si nous prévoyons d'utiliser AtomicLong, alors, selon la documentation, le débit attendu de LongAdder est considérablement plus élevé, au détriment d'une consommation d'espace plus élevée. Vérifiez également cette question .
la source
La solution la plus propre sans NullPointerException est:
la source
Comme je ne peux pas commenter quelques réponses en raison d'une réputation moindre, je publierai une solution que j'ai appliquée.
la source
Utilisez une
for
boucle pour incrémenter l'index:la source
Il y a ici des réponses trompeuses à cette question qui impliquent que la méthode put Hashtable remplacera la valeur existante si la clé existe, ce n'est pas vrai pour Hashtable mais plutôt pour HashMap. Voir Javadoc pour HashMap http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29
la source
ou
Entier correspond aux types de données primitifs http://cs.fit.edu/~ryan/java/language/java-data.html , vous devez donc les supprimer, effectuer un processus, puis les remettre. si vous avez une valeur qui n'est pas un type de données primitif, il vous suffit de la retirer, de la traiter, pas besoin de la remettre dans la table de hachage.
la source
Essayer:
REMARQUE:
Vous pouvez modifier la clé ou la valeur dans votre table de hachage, mais vous ne pouvez pas modifier les deux en même temps.
la source
Utilisez Java8 intégré dans fuction 'computeIfPresent'
Exemple:
la source