HashMap to return default value for non-found keys?

JavaDictionaryHashmap

Java Problem Overview


Is it possible to have a HashMap return a default value for all keys that are not found in the set?

Java Solutions


Solution 1 - Java

In Java 8, use Map.getOrDefault. It takes the key, and the value to return if no matching key is found.

Solution 2 - Java

[Update]

As noted by other answers and commenters, as of Java 8 you can simply call Map#getOrDefault(...).

[Original]

There's no Map implementation that does this exactly but it would be trivial to implement your own by extending HashMap:

public class DefaultHashMap<K,V> extends HashMap<K,V> {
  protected V defaultValue;
  public DefaultHashMap(V defaultValue) {
    this.defaultValue = defaultValue;
  }
  @Override
  public V get(Object k) {
    return containsKey(k) ? super.get(k) : defaultValue;
  }
}

Solution 3 - Java

Use Commons' DefaultedMap if you don't feel like reinventing the wheel, e.g.,

Map<String, String> map = new DefaultedMap<>("[NO ENTRY FOUND]");
String surname = map.get("Surname"); 
// surname == "[NO ENTRY FOUND]"

You can also pass in an existing map if you're not in charge of creating the map in the first place.

Solution 4 - Java

Java 8 introduced a nice computeIfAbsent default method to Map interface which stores lazy-computed value and so doesn't break map contract:

Map<Key, Graph> map = new HashMap<>();
map.computeIfAbsent(aKey, key -> createExpensiveGraph(key));

Origin: http://blog.javabien.net/2014/02/20/loadingcache-in-java-8-without-guava/

Disclamer: This answer doesn't match exactly what OP asked but may be handy in some cases matching question's title when keys number is limited and caching of different values would be profitable. It shouldn't be used in opposite case with plenty of keys and same default value as this would needlessly waste memory.

Solution 5 - Java

Can't you just create a static method that does exactly this?

private static <K, V> V getOrDefault(Map<K,V> map, K key, V defaultValue) {
    return map.containsKey(key) ? map.get(key) : defaultValue;
}

Solution 6 - Java

You can simply create a new class that inherits HashMap and add getDefault method. Here is a sample code:

public class DefaultHashMap<K,V> extends HashMap<K,V> {
    public V getDefault(K key, V defaultValue) {
        if (containsKey(key)) {
            return get(key);
        }
        
        return defaultValue;
    }
}

I think that you should not override get(K key) method in your implementation, because of the reasons specified by Ed Staub in his comment and because you will break the contract of Map interface (this can potentially lead to some hard-to-find bugs).

Solution 7 - Java

Use:

myHashMap.getOrDefault(key, defaultValue);

Solution 8 - Java

On java 8+

Map.getOrDefault(Object key,V defaultValue)

Solution 9 - Java

It does this by default. It returns null.

Solution 10 - Java

I found the LazyMap quite helpful.

> When the get(Object) method is called with a key that does not exist in the map, the factory is used to create the object. The created object will be added to the map using the requested key.

This allows you to do something like this:

    Map<String, AtomicInteger> map = LazyMap.lazyMap(new HashMap<>(), ()->new AtomicInteger(0));
    map.get(notExistingKey).incrementAndGet();

The call to get creates a default value for the given key. You specify how to create the default value with the factory argument to LazyMap.lazyMap(map, factory). In the example above, the map is initialized to a new AtomicInteger with value 0.

Solution 11 - Java

Not directly, but you can extend the class to modify its get method. Here is a ready to use example: http://www.java2s.com/Code/Java/Collections-Data-Structure/ExtendedVersionofjavautilHashMapthatprovidesanextendedgetmethodaccpetingadefaultvalue.htm

Solution 12 - Java

/**
 * Extension of TreeMap to provide default value getter/creator.
 * 
 * NOTE: This class performs no null key or value checking.
 * 
 * @author N David Brown
 *
 * @param <K>	Key type
 * @param <V>  	Value type
 */
public abstract class Hash<K, V> extends TreeMap<K, V> {

	private static final long serialVersionUID = 1905150272531272505L;

	/**
	 * Same as {@link #get(Object)} but first stores result of
	 * {@link #create(Object)} under given key if key doesn't exist.
	 * 
	 * @param k
	 * @return
	 */
	public V getOrCreate(final K k) {
		V v = get(k);
		if (v == null) {
			v = create(k);
			put(k, v);
		}
		return v;
	}

	/**
	 * Same as {@link #get(Object)} but returns specified default value
	 * if key doesn't exist. Note that default value isn't automatically
	 * stored under the given key.
	 * 
	 * @param k
	 * @param _default
	 * @return
	 */
	public V getDefault(final K k, final V _default) {
		V v = get(k);
		return v == null ? _default : v;
	}

	/**
	 * Creates a default value for the specified key.
	 * 
	 * @param k
	 * @return
	 */
	abstract protected V create(final K k);
}

Example Usage:

protected class HashList extends Hash<String, ArrayList<String>> {
	private static final long serialVersionUID = 6658900478219817746L;

	@Override
		public ArrayList<Short> create(Short key) {
			return new ArrayList<Short>();
		}
}

final HashList haystack = new HashList();
final String needle = "hide and";
haystack.getOrCreate(needle).add("seek")
System.out.println(haystack.get(needle).get(0));

Solution 13 - Java

I needed to read the results returned from a server in JSON where I couldn't guarantee the fields would be present. I'm using class org.json.simple.JSONObject which is derived from HashMap. Here are some helper functions I employed:

public static String getString( final JSONObject response, 
						        final String key ) 
{ return getString( response, key, "" ); }	
public static String getString( final JSONObject response, 
						        final String key, final String defVal ) 
{ return response.containsKey( key ) ? (String)response.get( key ) : defVal; }

public static long getLong( final JSONObject response, 
						    final String key ) 
{ return getLong( response, key, 0 ); }	
public static long getLong( final JSONObject response, 
						    final String key, final long defVal ) 
{ return response.containsKey( key ) ? (long)response.get( key ) : defVal; }

public static float getFloat( final JSONObject response, 
						      final String key ) 
{ return getFloat( response, key, 0.0f ); }	
public static float getFloat( final JSONObject response, 
						      final String key, final float defVal ) 
{ return response.containsKey( key ) ? (float)response.get( key ) : defVal; }

public static List<JSONObject> getList( final JSONObject response, 
										final String key ) 
{ return getList( response, key, new ArrayList<JSONObject>() ); }	
public static List<JSONObject> getList( final JSONObject response, 
										final String key, final List<JSONObject> defVal ) { 
	try { return response.containsKey( key ) ? (List<JSONObject>) response.get( key ) : defVal; }
	catch( ClassCastException e ) { return defVal; }
}	

Solution 14 - Java

    public final Map<String, List<String>> stringMap = new ConcurrentHashMap<String, List<String>>() {
        @Nullable
        @Override
        public List<String> get(@NonNull Object key) {
            return computeIfAbsent((String) key, s -> new ArrayList<String>());
        }
    };

HashMap cause dead loop, so use ConcurrentHashMap instead of HashMap,

Solution 15 - Java

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLarryView Question on Stackoverflow
Solution 1 - JavaSpychoView Answer on Stackoverflow
Solution 2 - JavamaericsView Answer on Stackoverflow
Solution 3 - JavaDave NewtonView Answer on Stackoverflow
Solution 4 - JavaVadzimView Answer on Stackoverflow
Solution 5 - JavaShervin AsgariView Answer on Stackoverflow
Solution 6 - JavaIvan MushketykView Answer on Stackoverflow
Solution 7 - JavaDiego AlvisView Answer on Stackoverflow
Solution 8 - JavaEduardoView Answer on Stackoverflow
Solution 9 - JavamrkhrtsView Answer on Stackoverflow
Solution 10 - JavaBenedikt KöppelView Answer on Stackoverflow
Solution 11 - JavapiokucView Answer on Stackoverflow
Solution 12 - JavaKomodoDaveView Answer on Stackoverflow
Solution 13 - JavaBuvinJView Answer on Stackoverflow
Solution 14 - JavaYessyView Answer on Stackoverflow
Solution 15 - JavaVadzimView Answer on Stackoverflow