Is there a good way to have a Map<String, ?> get and put ignoring case?

JavaMapCase Insensitive

Java Problem Overview


Is there a good way to have a Map<String, ?> get and put ignoring case?

Java Solutions


Solution 1 - Java

TreeMap extends Map and supports custom comparators.

String provides a default case insensitive comparator.

So:

final Map<String, ...> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);

The comparator does not take locale into account. Read more about it in its JavaDoc.

Solution 2 - Java

You could use CaseInsensitiveMap from Apache's Commons Collections.

Solution 3 - Java

Would it be possible to implement your own Map overriding put/get methods ?

public class CaseInsensitiveMap extends HashMap<String, String> {
    ...
    put(String key, String value) {
       super.put(key.toLowerCase(), value);
    }
    
    get(String key) {
       super.get(key.toLowercase());
    }
}

This approach does not force you to change your "key" type but your Map implementation.

Solution 4 - Java

You need a wrapper class for your String key with a case-insensitive equals() and hashCode() implementation. Use that instead of the String for the Map's key.

See an example implementation at http://www.java.happycodings.com/Java_Util_Package/code3.html I found it in 2 minutes of googling. Looks sensible to me, though I've never used it.

Solution 5 - Java

The three obvious solutions that spring to mind:

  • Normalise the case before using a String as a key (not Turkish locale works differently from the rest of the world).

  • Use a special object type designed to be used as key. This is a common idiom for dealing with composite keys.

  • Use a TreeMap with a Comparator that is case insensitive (possibly a PRIMARY or SECONDARY strength java.text.Collator). Unfortunately the Java library doesn't have a Comparator equivalent for hashCode/equals.

Solution 6 - Java

You could use my Apache licensed CaseInsensitiveMap discussed here. Unlike the Apache Commons version, it preserves the case of keys. It implements the map contract more strictly than TreeMap (plus has better concurrent semantics) (see the blog comments for details).

Solution 7 - Java

Trove4j can use custom hashing for a HashMap. This may however have performance implications given that hashcodes cannot be cached (although Trove4j may have found a way around this?). Wrapper objects (as described by John M) do not have this caching deficiency. Also see my other answer regarding TreeMap.

Solution 8 - Java

Check the accepted answer at the link below. https://stackoverflow.com/questions/3092710/how-to-check-for-key-in-a-map-irrespective-of-the-case

Bottom line is "The simplest solution is to simply convert all inputs to uppercase (or lowercase) before inserting/checking. You could even write your own Map wrapper that would do this to ensure consistency."

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
QuestionJoshuaView Question on Stackoverflow
Solution 1 - JavavolleyView Answer on Stackoverflow
Solution 2 - JavaEric WeilnauView Answer on Stackoverflow
Solution 3 - JavaGuidoView Answer on Stackoverflow
Solution 4 - JavaJohn MView Answer on Stackoverflow
Solution 5 - JavaTom Hawtin - tacklineView Answer on Stackoverflow
Solution 6 - JavaglynView Answer on Stackoverflow
Solution 7 - JavavolleyView Answer on Stackoverflow
Solution 8 - JavaKunjanView Answer on Stackoverflow