Puede que sea un poco tarde, pero aquí están mis dos centavos.
Si está utilizando Java 8, puede utilizar el método computeIfPresent . Si el valor para la clave especificada está presente y no es nulo, entonces intenta calcular una nueva asignación dada la clave y su valor asignado actual.
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]
También podemos hacer uso de otro método putIfAbsent para poner una clave. Si la clave especificada no está ya asociada a un valor (o está asignada a nulo), este método la asocia al valor dado y devuelve nulo; de lo contrario, devuelve el valor actual.
En caso de que el mapa se comparte a través de las discusiones a continuación, podemos hacer uso de ConcurrentHashMap
y AtomicInteger . Del documento:
Un AtomicInteger
es un valor int que puede actualizarse atómicamente. Un AtomicInteger se usa en aplicaciones tales como contadores incrementados atómicamente, y no se puede usar como reemplazo de un Integer. Sin embargo, esta clase sí extiende el Número para permitir el acceso uniforme de herramientas y utilidades que se ocupan de clases basadas en números.
Podemos usarlos como se muestra:
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 a tener en cuenta es que estamos invocando get
para obtener el valor de la clave B
y luego invocando incrementAndGet()
su valor, que es, por supuesto AtomicInteger
. Podemos optimizarlo ya que el método putIfAbsent
devuelve el valor de la clave si ya está presente:
map2.putIfAbsent("B",new AtomicInteger(0)).incrementAndGet();//[A=0, B=2]
En una nota al margen si planeamos usar AtomicLong, entonces, según la documentación bajo alta contención, el rendimiento esperado de LongAdder es significativamente mayor, a expensas de un mayor consumo de espacio. También revise esta pregunta .