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.
final Map<String,Integer> map1 = new HashMap<>();
map1.put("A",0);
map1.put("B",0);
map1.computeIfPresent("B",(k,v)->v+1); //[A=0, B=1]
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:
An AtomicInteger
est une valeur int qui peut être mise à jour atomiquement. Un AtomicInteger est utilisé dans des applications telles que les compteurs à incrémentation atomique et ne peut pas être utilisé en remplacement d'un Integer. Cependant, cette classe étend Number pour permettre un accès uniforme par des outils et des utilitaires qui traitent des classes à base numérique.
Nous pouvons les utiliser comme indiqué:
final Map<String,AtomicInteger> map2 = new ConcurrentHashMap<>();
map2.putIfAbsent("A",new AtomicInteger(0));
map2.putIfAbsent("B",new AtomicInteger(0)); //[A=0, B=0]
map2.get("B").incrementAndGet(); //[A=0, B=1]
Un point à observer est que nous invoquons get
pour obtenir la valeur de la clé B
, puis invoquons incrementAndGet()
sa valeur qui est bien sûr AtomicInteger
. Nous pouvons l'optimiser car la méthode putIfAbsent
renvoie la valeur de la clé si elle est déjà présente:
map2.putIfAbsent("B",new AtomicInteger(0)).incrementAndGet();//[A=0, B=2]
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 .