Is this a valid code to write,if I wish to avoid unnecessary contains call?
I wish to avoid a contains call on every invocation,as this is highly time sensitive code.
cancelretryCountMap.putIfAbsent(tag,new AtomicInteger(0));
count = cancelretryCountMap.get(tag).incrementAndGet();
if(count > 10){
///abort after x retries
....
}
I am using JDK 7
Usually, you would use putIfAbsent
like this:
final AtomicInteger present = map.get(tag);
int count;
if (present != null) {
count = present.incrementAndGet();
} else {
final AtomicInteger instance = new AtomicInteger(0);
final AtomicInteger marker = map.putIfAbsent(tag, instance);
if (marker == null) {
count = instance.incrementAndGet();
} else {
count = marker.incrementAndGet();
}
}
The reason for the explicit get
being, that you want to avoid the allocation of the default value in the "happy" path (i.e., when there is already an entry with the given key).
If there is no matching entry, you have to use the return value of putIfAbsent
in order to distinguish between
null
, andget
(in which case the method returns the current value associated with the given key)You can abstract this sequence by introducing a helper method, e.g.,
interface Supplier<T> {
T get();
}
static <T> T computeIfAbsent(ConcurrentMap<K,T> map, T key, Supplier<? extends T> producer) {
final T present = map.get(key);
if (present != null) {
return present;
} else {
final T fallback = producer.get();
final T marker = map.putIfAbsent(key, fallback);
if (marker == null) {
return fallback;
} else {
return marker;
}
}
}
You could use this in your example:
static final Supplier<AtomicInteger> newAtomicInteger = new Supplier<AtomicInteger>() {
public AtomicInteger get() { return new AtomicInteger(0); }
};
void yourMethodWhatever(Object tag) {
final AtomicInteger counter = computeIfAbsent(cancelretryCountMap, tag, newAtomicInteger);
if (counter.incrementAndGet() > 10) {
... whatever ...
}
}
Note, that this is actually already provided in the JDK 8 as default
method on Map
, but since you are still on JDK 7, you have to roll your own, as is done here.