I am trying to rework some of my methods to make them more concise using Java 8, whose new features I am trying to slowly absorb.
It is a method with the purpose of adding a value
to a Map<Key, Set<Value>>
. There are three posibilities:
null
, because I have some preconditions to deal with that.IllegalArgumentException
is thrown.The code implementing this behaviour is the following, and it does not use Java 8 features:
public void addValue(Key key, Value value) {
// irrelevant preconditions...
Set<Value> valuesForKey = myMap.get(key);
if (valuesForKey != null && valuesForKey.contains(value))
throw new IllegalArgumentException("Association exists already");
if (valuesForKey == null)
myMap.put(key, new HashSet<Value>(Arrays.asList(value)));
else
valuesForKey.add(value);
}
I would like to shorten this code using Java 8 methods like computeIfAbsent.
I could sum up the last if-else
block, but I can't get past the redundancy of the value set to which key
maps to having already being retrieved when performing the precondition checks.
public void addValue(Key key, Value value) {
// irrelevant preconditions...
Set<Value> valuesForKey = myMap.get(key);
if (valuesForKey != null && valuesForKey.contains(value))
throw new IllegalArgumentException("Association exists already");
myMap.computeIfAbsent(key, v -> new HashSet<Value>()).add(value);
}
Is there anyway I could merge all that in one instruction?
The computeIfAbsent(Key, Function) method of HashMap class is used to compute value for a given key using the given mapping function, if key is not already associated with a value (or is mapped to null) and enter that computed value in Hashmap else null.
computeIfAbsent. If the specified key is not already associated with a value (or is mapped to null ), attempts to compute its value using the given mapping function and enters it into this map unless null .
Both functions aspire to add an element if the specified Key is not already present in Map. putIfAbsent adds an element with the specified Value whereas computeIfAbsent adds an element with the value computed using the Key.
The 'computeIfAbsent(..)' function essentially has 3 steps: (1) see that the value is missing, (2) compute the Function, and (3) store the value in the map. Since this is atomic, there cannot be an interleaving of two threads where A does step 1, then B does 1, then both do steps 2 and then 3.
You can take advantage of the fact that the add(element)
method will return true
if the set didn't contain the specified element. If this call returns false
, it means the element wasn't added because it was already present. Therefore, you can use:
public void addValue(Key key, Value value) {
boolean added = myMap.computeIfAbsent(key, k -> new HashSet<>()).add(value);
if (!added) {
throw new IllegalArgumentException("Association exists already");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With