* @param factory It creates an object, if it is not present in the map already.
*/
public <P1, P2> V putIfAbsentGetIfPresent(K key, Function2<K, V, K> keyTransformer, Function3<P1, P2, K, V> factory, P1 param1, P2 param2)
{
int hash = this.hash(key);
AtomicReferenceArray currentArray = this.table;
V newValue = null;
boolean createdValue = false;
while (true)
{
int length = currentArray.length();
int index = ConcurrentHashMap.indexFor(hash, length);
Object o = currentArray.get(index);
if (o == RESIZED || o == RESIZING)
{
currentArray = this.helpWithResizeWhileCurrentIndex(currentArray, index);
}
else
{
Entry<K, V> e = (Entry<K, V>) o;
while (e != null)
{
Object candidate = e.getKey();
if (candidate.equals(key))
{
return e.getValue();
}
e = e.getNext();
}
if (!createdValue)
{
createdValue = true;
newValue = factory.value(param1, param2, key);
if (newValue == null)
{
return null; // null value means no mapping is required
}
key = keyTransformer.value(key, newValue);
}
Entry<K, V> newEntry = new Entry<K, V>(key, newValue, (Entry<K, V>) o);
if (currentArray.compareAndSet(index, o, newEntry))
{
this.incrementSizeAndPossiblyResize(currentArray, length, o);
return null;
}
}