I need to make async calls with a timeout of 10 seconds, and need to perform this for every element from a map. The results of the async calls are stored in another map. Is it safe to use a HashMap
in this case or do I need to use ConcurrentMap
?
Map<String, String> x = ArrayListMultimap.create();
Map<String, Boolean> value = Maps.newHashMap();
x.keySet().paralleStream().forEach(req -> {
try {
Response response = getResponseForRequest(req);
value.put(req, response.getTitle());
} catch(TimeoutException e) {
value.put(req, null);
}
}
Is this thread safe? I'm not able to figure out. I know the alternative way is to create a concurrent hashmap, and think of some other filler value instead of null as Concurrent maps dont support null values.
You can use .map()
instead of .forEach()
and return a map created with Collectors.toMap()
terminating function instead of modifying external map in parallel. Consider following example:
Map result = x.keySet()
.parallelStream()
.map(req -> {
try {
Response response = getResponseForRequest(req);
return new AbstractMap.SimpleEntry<>(req, response.getTitle());
} catch (TimeoutException e) {
return new AbstractMap.SimpleEntry<>(req, null);
}
})
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
In this example you return a SimpleEntry
object that represents a key and value for each element and when all entries are processed you collect them to a single map.
Holger suggested even more simplified solution by getting rid of AbstractMap.SimpleEntry
at all:
Map result = x.keySet()
.parallelStream()
.collect(Collectors.toMap(Function.identity(), req -> {
try {
Response response = getResponseForRequest(req);
return response.getTitle()
} catch (TimeoutException e) {
return null
}
}));
Pick whatever works better for you.