Domanda

In Java, I want to add a getOrAdd method to a regular map, just like putIfAbsent on a ConcurrentHashMap.

Furthermore, for a certain key I want to store a list of items. Here's my attempt:

public class ListMap<K, V> extends HashMap<K, V> {

    private HashMap<K, List<V>> map;

    public ListMap() {
        map = new HashMap<K, List<V>>();
    }

    public List<V> getOrAdd(K key) {
        if (map.containsKey(key)) {
            return map.get(key);
        } else {
            List<V> l = new ArrayList<V>();
            map.put(key, l);
            return l;
        }
    }
}

However, if someone wanted to iterate over a ListMap, he would need to cast the values explictly.

ListMap<Integer, MyClass> listMap = new ListMap<Integer, MyClass>();
for (Map.Entry<Integer, MyClass> entry : listMap.entrySet()) {
    List<MyClass> val = (List<MyClass>) entry.getValue();
}
  1. Is there a way of extending the HashMap class by some methods without creating a subclass? ( I've seen this in C#)

  2. How can the ListMap class be modified such that one can get a ListMaps's value (List) without casting?

È stato utile?

Soluzione

Instance of your class will be also HashMap so you don't need to, or even shouldn't add another field just to support getOrAdd method because other inherited and not overridden methods will not be referring to map field but to this instance.

So instead of adding separate field

private HashMap<K, List<V>> map;

change extending type of your ListMap to

public class ListMap<K, V> extends HashMap<K, List<V>> 
                                              ^^^^^^^

and change your getOrAdd method to not use map field but this

public List<V> getOrAdd(K key) {
    if (containsKey(key)) {
        return get(key);
    } else {
        List<V> l = new ArrayList<V>();
        put(key, l);
        return l;
    }
}

This change will let you use your map like

ListMap<Integer, String> listMap = new ListMap<Integer, String>();
for (Map.Entry<Integer, List<String>> entry : listMap.entrySet()) {
    List<String> val = entry.getValue();//NO CASTING NEEDED
}

Altri suggerimenti

You can just extend HashMap like this:

public class ListMap<K, V> extends HashMap<K, List<V>> {
...
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top