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

- 38,421
- 18
- 121
- 193

- 26,234
- 22
- 77
- 106
-
Similar question: http://stackoverflow.com/questions/8236945/case-insensitive-string-as-hashmap-key – Vadzim Sep 11 '15 at 12:27
8 Answers
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.

- 6,651
- 1
- 27
- 28
-
4Note that you don't need to worry about locale *if you control the keys that are being used* and not your end users, and your keys are english. – Brad Parks Mar 10 '14 at 15:07
-
If you need a Map that allows nulls, which TreeMap does not support, try the CaseInsenstiveMap at https://github.com/jdereg/java-util. This one accesses the Map in O(1) unlike TreeMap which is O(log n). – John DeRegnaucourt Mar 04 '16 at 08:20
You could use CaseInsensitiveMap from Apache's Commons Collections.

- 5,370
- 4
- 30
- 30
-
1note that CaseInsensitiveMap [is not generic](http://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/map/CaseInsensitiveMap.html), so you cannot do `Map
` with that. – eis Sep 04 '13 at 12:52 -
6
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.
-
4That is basically the approach taken in Apache's Commons Collections CaseInsensitiveMap. – Eric Weilnau Oct 17 '08 at 15:27
-
4Remember to use a locale when doing upper and lower case operations. – marcospereira Oct 17 '08 at 15:28
-
3
-
11One strange side-effect is that if you list the keys in this map, they will suddenly have turned lowercase. – volley Oct 17 '08 at 22:19
-
2Don't like the idea of extending HashMap, why not make a delegator like: CaseInsensitiveMap
which implements Map – gub Nov 10 '11 at 16:45, and that takes a Map as a constructor argument? -
4Don't forget containsKey and mind problems if you transfer its contents into another map. – stracktracer Mar 15 '12 at 08:56
-
2
-
2Beware of doing this in JDK8. The implementation has changed and you now need to override get, put and putAll in order for this to be consistent. – Steve N Apr 05 '14 at 10:46
-
Please warn users here about the danger of locale-sensitive `toLowercase()` issues! – ŁukaszBachman Jun 03 '14 at 08:10
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.

- 13,053
- 3
- 27
- 26
-
A little tricky, isn't it? I don't like to implement equals, and hashCode avove all, if it is not really really needed. I prefer the aproach of creating a Map implementation overriding put and get methods. – Guido Oct 17 '08 at 15:40
-
1Creating a wrapper class is done all the time and is not tricky at all. The wrapper class solution is also much cleaner that overriding put, get, putAll. You can use the wrapper class on any hashed or equals based collection (HashSet, HashMap, ArrayList, etc). – Steve Kuo Oct 17 '08 at 16:53
-
The portability among different collections is interesting. Thank you. I didn't think about it. I suppose each approach has its advantages and drawbacks. – Guido Oct 17 '08 at 18:03
-
Another good reason to use the wrapper class is that if you want to preserve the original case of the string, it's impossible to do it with the override of the put. – Sauleil Aug 16 '10 at 17:09
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.

- 145,806
- 30
- 211
- 305
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).

- 1,180
- 8
- 19
Check the accepted answer at the link below. 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."
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.

- 6,651
- 1
- 27
- 28