Potrebbe essere un po 'tardi, ma ecco i miei due centesimi.
Se si utilizza Java 8, è possibile utilizzare il metodo computeIfPresent . Se il valore per la chiave specificata è presente e non nullo, tenta di calcolare una nuova mappatura data la chiave e il suo valore corrente mappato.
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]
Possiamo anche usare un altro metodo putIfAbsent per mettere una chiave. Se la chiave specificata non è già associata a un valore (o è mappata su null), questo metodo la associa al valore dato e restituisce null, altrimenti restituisce il valore corrente.
Nel caso in cui la mappa è condivisa tra le discussioni allora possiamo fare uso di ConcurrentHashMap
e AtomicInteger . Dal documento:
An AtomicInteger
è un valore int che può essere aggiornato atomicamente. Un AtomicInteger viene utilizzato in applicazioni come contatori a incremento atomico e non può essere utilizzato come sostituto di un numero intero. Tuttavia, questa classe estende il numero per consentire l'accesso uniforme da parte di strumenti e utilità che si occupano di classi basate su valori numerici.
Possiamo usarli come mostrato:
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 punto da osservare è che stiamo invocando get
per ottenere il valore per chiave B
e quindi invocando incrementAndGet()
il suo valore che è ovviamente AtomicInteger
. Possiamo ottimizzarlo poiché il metodo putIfAbsent
restituisce il valore per la chiave se già presente:
map2.putIfAbsent("B",new AtomicInteger(0)).incrementAndGet();//[A=0, B=2]
In una nota a margine se intendiamo utilizzare AtomicLong, come da documentazione in contesa elevata, il throughput previsto di LongAdder è significativamente più alto, a scapito di un maggiore consumo di spazio. Controlla anche questa domanda .