Java не допускает какой-либо формы короткого замыкания, за исключением встроенных случаев, к сожалению - все вызовы метода приводят к полной оценке аргументов перед передачей управления методу. Таким образом, вы не можете сделать это с «нормальным» синтаксисом; вам нужно будет вручную обернуть вычисление в Callable
или подобное, а затем явно вызвать его.
В этом случае мне трудно понять, как это все равно может работать. putIfAbsent
работает на основе атомарной неблокирующей операции. Если бы он делал то, что вы хотите, последовательность событий была бы примерно такой:
- Проверьте, существует ли
key
на карте (в этом примере предполагается, что его нет)
- Оцените
calculatedValue
(вероятно, дорого, учитывая контекст вопроса)
- Положить результат на карту
Было бы невозможно, чтобы это было неблокирующим, если значение еще не существовало на втором шаге - два разных потока, вызывающих этот метод одновременно, могли бы работать правильно только в случае блокировки. На этом этапе вы можете просто использовать synchronized
блоки с гибкостью реализации, которая влечет за собой; Вы можете определенно реализовать то, что вам нужно, с помощью некоторой простой блокировки, например:
private final Map<K, V> map = ...;
public void myAdd(K key, Callable<V> valueComputation) {
synchronized(map) {
if (!map.containsKey(key)) {
map.put(key, valueComputation.call());
}
}
}