1

I came across this post for a case insensitive hashmap and tried to implement it but I'm not getting the expected result. For some reason it's not returning the value when I do get with a different casing and is returning null, and I thought that you didn't really need a non-default constructor in this case but I'm not sure.

public class CaseInsensitiveMap extends HashMap<String, Integer> {

    @Override
    public Integer put(String key, Integer value) {
       return super.put(key.toLowerCase(), value);
    }

    // not @Override because that would require the key parameter to be of type Object
    public Integer get(String key) {
       return super.get(key.toLowerCase());
    }
}

and used like so;

HashMap<String, Integer> stuff = new CaseInsensitiveMap();
stuff.put("happy", 11);
System.out.println(stuff);
Integer result = stuff.get("HAPPy");
System.out.println(result);
System.out.println(stuff);

but result is;

{happy=11}
null
{happy=11}
buræquete
  • 14,226
  • 4
  • 44
  • 89
Shinji-san
  • 971
  • 4
  • 14
  • 31

2 Answers2

2

Simple fix;

CaseInsensitiveMap stuff = new CaseInsensitiveMap();

prints out;

{happy=11}
11
{happy=11}

CaseInsensitiveMap is extending HashMap<String, Integer> so it is a subclass of it, the fact that you reference stuff as HashMap (as the superclass) allows it to use default get method. You can even see in an IDE that your custom get(String) in CaseInsensitiveMap is not even used.

Only overridden methods will be used if you use superclass reference for a subclass, as you've done in your code. That is why only your custom put(String, Integer) method works since it is overriding the method in super.

Referencing Subclass objects with Subclass vs Superclass reference for more info on that issue.

buræquete
  • 14,226
  • 4
  • 44
  • 89
1

As String is marked as final, may consider extends CharSequence

public class CaseInsensitiveMap<K extends CharSequence, V> implements Map<K, V> {

    private Map<K, V> map = new HashMap<K, V>();

    @Override
    public int size() {
        return map.size();
    }

    @Override
    public boolean isEmpty() {
        return map.isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return map.containsKey(key.toString().toLowerCase());
    }

    @Override
    public boolean containsValue(Object value) {
        return map.containsValue(value);
    }

    @Override
    public V get(Object key) {
        return map.get(key.toString().toLowerCase());
    }

    @Override
    public V put(K key, V value) {
        return map.put((K) key.toString().toLowerCase(), value);
    }

    @Override
    public V remove(Object key) {
        return map.remove(key.toString().toLowerCase());
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        map.putAll(m);      
    }

    @Override
    public void clear() {
        map.clear();
    }

    @Override
    public Set<K> keySet() {
        return map.keySet();
    }

    @Override
    public Collection<V> values() {
        return map.values();
    }

    @Override
    public Set<java.util.Map.Entry<K, V> > entrySet() {
        return map.entrySet();
    }

    @Override
    public String toString() {
        return map.toString();
    }

}

The testing class needed to modified as the following:

public class Tester {

    public static void main(String[] args) {

        Map<String, Integer> stuff = new CaseInsensitiveMap<String, Integer>();

        stuff.put("happy", 11);
        System.out.println(stuff);
        Integer result = stuff.get("HAPPy");
        System.out.println(result);
        System.out.println(stuff);

    }
}
buræquete
  • 14,226
  • 4
  • 44
  • 89
Miller Cy Chan
  • 897
  • 9
  • 19