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?

+3


source to share


1 answer


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.

+3


source







All Articles