A suggestion: Map.checkAndGet

David Holmes david.holmes at oracle.com
Wed Oct 31 18:11:06 PDT 2012


On 1/11/2012 1:44 AM, Zhong Yu wrote:
> How can we add any default method to an interface, since its behavior
> might conflict with some unknown subclass' unknown additional
> contracts?

This is a risk that has to be taken to allow the platform to evolve. We 
can mitigate it by considering the "obvious" kinds of specialization but 
we can not avoid them.

Thread-safety is a very obvious candidate here and there are 
implications for both concurrent data structures (like 
ConcurrentHashMap) and simpler thread-safe structures, like the 
synchronized collection wrappers. For issues within the JDK libraries we 
have to solve any problems that arise. For issues external to the JDK 
this just has to be part of the JDK8 migration process.

In some cases it may be necessary to re-abstract new methods so that the 
default implementation is not used. For example if someone has a 
ConcurrentList interface for which new default implementations in List 
would not be thread-safe, then ConcurrentList should be updated to 
re-abstract those methods (ie re-define them with no default 
implementation). Of course inside the JDK we would have to ensure there 
are correct, concrete implementations for all of the concrete types.

David
-----


>
> On Tue, Oct 30, 2012 at 11:49 AM, Mike Duigou<mike.duigou at oracle.com>  wrote:
>> Unfortunately such a method would introduce non-atomic behaviour for synchronized maps so we can't add it.
>>
>> Mike
>>
>> On Oct 30 2012, at 08:25 , Boaz Nahum wrote:
>>
>>> The pattern
>>> map.containsKey(k) ? map.get() : othervAlue
>>> (walks on tree twice)
>>>
>>> repeats itself so many times, as in Mappers:
>>>
>>> public static<T, U>  Mapper<T, U>  forMap(Map<? super T, ? extends U>  map,
>>> U defaultValue) {
>>>         Objects.requireNonNull(map);
>>>
>>>         return t ->  map.containsKey(t) ? map.get(t) : defaultValue;
>>> }
>>>
>>>
>>> Now that we have 'default methods', we can add to Map:
>>>
>>> NullableOptional<V>  checkAndget(K key) default {
>>>
>>>         if (containsKey(key)) {
>>>             return new NullableOptional<>(get(key));
>>>         } else {
>>>             return NullableOptional.empty();
>>>         }
>>>     }
>>>
>>> **and** implement it in Map implementation in such way that will walk on
>>> tree only once.
>>> (Assume creating instance of NullableOptional is more  efficient )
>>>
>>> forMap becomes:
>>>
>>> public static<T, U>  Mapper<T, U>  forMap(MyMap<? super T, ? extends U>  map,
>>> U defaultValue) {
>>>         Objects.requireNonNull(map);
>>>
>>>
>>>         return t ->  {
>>>             NullableOptional<? extends U>  o = map.checkAndget(t);
>>>             return o.isPresent() ? o.get() : defaultValue;
>>>             //return o.orElse(defaultValue);
>>>         };
>>>     }
>>>
>>
>>
>


More information about the lambda-dev mailing list