Можливо, буде трохи пізно, але ось два мої центи.
Якщо ви використовуєте Java 8, то ви можете скористатися методом computeIfPresent . Якщо значення для вказаного ключа присутнє та ненулеве, воно намагається обчислити нове відображення з урахуванням ключа та його поточного відображеного значення.
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]
Ми також можемо скористатися іншим методом putIfAbsent, щоб поставити ключ. Якщо вказаний ключ вже не асоційований із значенням (або відображається на нульовому значенні), цей метод пов'язує його із заданим значенням та повертає нульове значення, інше повертає поточне значення.
Якщо карта поділяється на нитки, ми можемо скористатись ConcurrentHashMap
і AtomicInteger . Від док.
AtomicInteger
Є INT значення , яке може оновлюватися атомарному. AtomicInteger використовується в таких додатках, як атомно-примножений лічильник, і його не можна використовувати як заміну цілого числа. Однак цей клас поширює номер, щоб дозволити рівномірний доступ до інструментів та утиліт, які працюють з класами на основі чисельності.
Ми можемо використовувати їх як показано:
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]
Одним із моментів, який слід зазначити, є те, що ми звертаємось get
до отримання значення ключа, B
а потім - incrementAndGet()
його значення, звичайно AtomicInteger
. Ми можемо оптимізувати його, оскільки метод putIfAbsent
повертає значення для ключа, якщо він вже є:
map2.putIfAbsent("B",new AtomicInteger(0)).incrementAndGet();//[A=0, B=2]
З іншого боку, якщо ми плануємо використовувати AtomicLong, то відповідно до документації за великої суперечності очікувана пропускна здатність LongAdder значно вище, за рахунок більшого споживання місця. Також перевірте це питання .