I am using an object of type
Map<Long, Map<UUID, OperationEntry>> stepOperations = new ConcurrentHashMap<>();
to control the execution of some operations. I have a Kafka message handler method that, upon receiving a message about a status change of an operation, needs to find and update the state of a record in stepOperations map based on the passed UUID.
UUID class is not overriden (standatd java.util.UUID).
What could be the reason for getting an unexpected result from the containsKey method if the key "3102869c-7653-4fb7-ad47-a629b5cbac90", as clearly seen in the screenshot, is present in the map?
Here is the problematic part of the code:
private OperationEntry getOperationLogEntry(UUID requestId) {
return stepOperations.values().stream()
.filter(value -> value.containsKey(requestId))
.map(value -> value.get(requestId))
.findFirst()
.orElse(null);
}
The ConcurrentHashMap class is used due to its guaranted support for multithreaded processing. The incoming Kafka messages are processed by a thread pool consisting of 16 threads.
Could the presence of a inner map be a potential issue here?
Simple test such as
Map<UUID, String> testMap = new java.util.concurrent.ConcurrentHashMap<>();
UUID key = UUID.randomUUID();
testMap.put(key, "testValue");
if (testMap.containsKey(key)) {
System.out.println(testMap.get(key));
}
works as it's expected to be
In the debugger, we can see that
valuevariable in anHashMap. Not aConcurrentHashMap:When you work with multi levels of map, you should use
computeIfAbsent.From your code, you should probably:
stepOperationsbeConcurrentMap<Long, ConcurrentMap<UUID, Whatever>>to make sure the two levels are good.computeIfAbsentas instepOperations.computeIfAbsent(key, ignored -> new ConcurrentHashMap<>())To add a new step:
Finally, you could probably rewrite your code:
Do that instead:
Two points:
idto ensure you use the same idConcurrentHashMapforbids key and value from beingnull: thecontainsKeyis useless here.