net.sf.javagimmicks.collections.AutoFillingMapDecorator Maven / Gradle / Ivy
package net.sf.javagimmicks.collections;
import java.util.Map;
import net.sf.javagimmicks.collections.decorators.AbstractMapDecorator;
import net.sf.javagimmicks.util.Supplier;
/**
* A special {@link Map} decorator that wraps a given {@link Map} and there
* automatically fills in (default) values if a call to {@link #get(Object)}
* tries to receive the value for a not yet contained key. This is useful in
* some special cases e.g. if {@link NullPointerException}s should be avoided
* and there is some logic for creating default values.
*
* Default values for auto-filling have to be provided/generated via a given
* {@link Supplier}.
*
* @param
* the type of keys
* @param
* the type of values
*/
public class AutoFillingMapDecorator extends AbstractMapDecorator
{
private static final long serialVersionUID = -955460173448590006L;
/**
* Decorates a given {@link Map} using the given {@link Supplier} for
* generating default values.
*
* @param decorated
* the {@link Map} to wrap
* @param valueFactory
* the {@link Supplier} to use for generating default values
* @param
* the type of the keys
* @param
* the type of the values
* @return the resulting wrapped {@link Map}
*/
public static Map decorate(final Map decorated, final Supplier valueFactory)
{
return new AutoFillingMapDecorator(decorated, valueFactory);
}
protected final Supplier _valueFactory;
protected AutoFillingMapDecorator(final Map decorated, final Supplier valueFactory)
{
super(decorated);
_valueFactory = valueFactory;
}
/**
* Re-implements the default behavior in the following way:
*
* - If the given key does exist in the underlying {@link Map}, return the
* associated value (may be
null
)
* - If the given key does not yet exist in the underlying {@link Map}
*
* - Call the underlying {@link Supplier} the receive a default value
* - Perform a {@link #put(Object, Object)} with the given key and new
* default value on the underlying {@link Map}
*
- Return the default value
*
*
*/
@Override
@SuppressWarnings("unchecked")
public V get(final Object key)
{
if (!containsKey(key))
{
put((K) key, _valueFactory.get());
}
return super.get(key);
}
}