Do collection functions have functional methods such as get, put, etc.?
I have been working with Java 1.6 for many years (maintaining legacy tools) and I just started migrating to 1.8. One big change is the functional methods in the java.util.Collections collection. My biggest concern is that I have several collection extensions that apply rigorous checks or modification algorithms. Do the default methods use the already defined functions put (..), get (...), remove (..), etc. Or do I need to do a lot of work to make this work?
eg. (ignoring null checks, etc. a map that only contains values <= 10)
public class LimitedMap extends HashMap<String, Integer>{
@Override
public Integer put(String key, Integer value){
if(value> 10) throw new IllegalArgumentException();
return super.put(key, value);
}
@Override
public Integer computeIfAbsent(String key, Function<? super String, ? extends Integer> mappingFunction) {
return super.computeIfAbsent(key, mappingFunction);
}
}
With this pair of functions: do I still need to do a detailed override and put the new checks in the computeIfAbsent function?
source to share
The only way to ensure that only interface methods from pre Java 8 can be used is if you somehow delegate the default method implementation in the interface ( Map<K, V>
in this case).
That is, if you could write something like the following (which you cannot).
public class LimitedMap extends HashMap<String, Integer> {
@Override
public Integer computeIfAbsent(String key,
Function<? super String, ? extends Integer> mappingFunction) {
return Map.super.computeIfAbsent(key, mappingFunction);
}
}
Unfortunately, this is not legal, as you can only call a method that you overridden (here is one of HashMap<String, Integer>
), but not one that an inherited method could override (these are the usual rules for super
method invocation).
Thus, the only workaround I can see for your situation is to create a copy of the default method implementation of the interface in a helper class like this:
public class Maps {
public static <K, V> V computeIfAbsent(Map<K, V> map,
K key, Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
V v;
if ((v = map.get(key)) == null) {
V newValue;
if ((newValue = mappingFunction.apply(key)) != null) {
map.put(key, newValue);
return newValue;
}
}
return v;
}
}
It is implemented java.util.Map
as a static method, extended with an additional parameter map
for the instance for which it is running.
With a helper class like this, you can now write
public class LimitedMap extends HashMap<String, Integer> {
@Override
public Integer computeIfAbsent(String key,
Function<? super String, ? extends Integer> mappingFunction) {
return Maps.computeIfAbsent(this, key, mappingFunction);
}
}
This is not a great solution, except for one, which should work with a limited amount of effort.
source to share