Może być trochę późno, ale oto moje dwa centy.
Jeśli używasz Java 8, możesz skorzystać z metody computeIfPresent . Jeśli wartość określonego klucza jest obecna i ma wartość inną niż null, wówczas próbuje obliczyć nowe odwzorowanie, biorąc pod uwagę klucz i jego bieżącą wartość odwzorowaną.
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]
Możemy również użyć innej metody putIfAbsent do wprowadzenia klucza. Jeśli określony klucz nie jest już powiązany z wartością (lub jest odwzorowany na wartość NULL), wówczas ta metoda wiąże go z podaną wartością i zwraca wartość NULL, w przeciwnym razie zwraca bieżącą wartość.
W przypadku, gdy mapa jest wspólna dla wątków następnie możemy wykorzystać ConcurrentHashMap
i AtomicInteger . Z dokumentu:
An AtomicInteger
jest wartością całkowitą, która może być aktualizowana atomowo. AtomicInteger jest używany w aplikacjach takich jak liczniki z przyrostem atomowym i nie może być stosowany jako zamiennik liczby całkowitej. Jednak ta klasa rozszerza liczbę, aby umożliwić jednolity dostęp do narzędzi i programów narzędziowych, które zajmują się klasami opartymi na liczbach.
Możemy ich używać, jak pokazano:
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]
Należy zauważyć, że wzywamy, get
aby uzyskać wartość klucza, B
a następnie wywołujemy incrementAndGet()
jej wartość, co oczywiście jest AtomicInteger
. Możemy go zoptymalizować, ponieważ metoda putIfAbsent
zwraca wartość klucza, jeśli już istnieje:
map2.putIfAbsent("B",new AtomicInteger(0)).incrementAndGet();//[A=0, B=2]
Na marginesie, jeśli planujemy użyć AtomicLong, to zgodnie z dokumentacją w wysokiej rywalizacji spodziewana przepustowość LongAdder jest znacznie wyższa, kosztem wyższego zużycia miejsca. Sprawdź także to pytanie .