Creating a Java Map with Case-Insensitive Keys

Maps are one of the most widely used data structures in Java. A Map is a collection that contains key-value pairs. As one of the requirements, Map keys should be immutable.

Due to their immutable nature, Strings are widely used as keys in Maps. By default, String keys in a Map are case-sensitive. This tutorial will show how we can create a Map with case-insensitive keys.

1. Case-Sensitive vs. Case-Insensitive Maps

Let us first understand the basic difference between a case-sensitive and a case-insensitive Map.

As mentioned earlier, by default keys will be case-sensitive. Suppose we have a Map with String as the Key and Integer numbers as the values. Let us add an entry into the Map.

caseSensitiveMap.put("A", 1);   //{A=1}

Let’s add another entry with the same key but in a small case notation. As the keys are case-sensitive, they will be treated as distinct keys. Now, the contents of the Map will be {A=1, a=2}.

caseSensitiveMap.put("A", 1);   //{A=1}
caseSensitiveMap.put("a", 2);  //{A=1, a=2}

Now, repeat the same thing with a case-insensitive Map. We will add the same entries to this Map. As the keys are case-insensitive, “A” and “a” would be treated as the same keys.

caseInsensitiveMap.put("A", 1);   //{A=1}
caseInsensitiveMap.put("a", 2);   //{A=2}

2. Creating Case-Insensitive Maps

2.1. Using TreeMap with CASE_INSENSITIVE_ORDER Comparator

TreeMap provides an efficient way to store key/value pairs in sorted order. TreeMap does not allow null keys. As TreeMap stores the keys in sorted order, we can specify the sort order using a Comparator which for our use-case would be String.CASE_INSENSITIVE_ORDER.

The String.CASE_INSENSITIVE_ORDER gives back a Comparator that compares two Strings by ignoring their case. As the case of the keys will be ignored, we will only find one entry in the Map.

Map<String, Integer> caseInsensitiveTreeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);

caseInsensitiveTreeMap.put("AA", 1);    //{AA=1}
caseInsensitiveTreeMap.put("aa", 2);    //{AA=2}

We can also verify the case-insensitive nature by removing a key in a different case. Post this removal, the size of the Map would be Zero.

caseInsensitiveTreeMap.remove("aA");   //Remove the entry from map

TreeMap does not provide constant-time performance for basic operations like get() and put(). It is not an issue for most applications, but worth keeping in mind if we have a performance-critical application.

2.2. Using CaseInsensitiveMap

CaseInsensitiveMap class is part of Apache Commons Collections. Since it is an external library, add its latest dependency from Maven repo. If you’re using Maven, add the dependency as follows:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>

CaseInsensitiveMap stores the keys in lowercase. And null keys are also supported.

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

caseInsensitiveMap.put("A", 1);      //{A=1}
caseInsensitiveMap.put("B", 2);     //{A=1, B=2}
caseInsensitiveMap.put(null, 3);   //{A=1, B=2, null=3}

caseInsensitiveMap.put("a", 4);     //{a=4, B=2, null=3}

Note that the key “B” was converted to lowercase and stored in the Map as “b”.

Again, the removal is also case-insensitive to the keys.

caseInsensitiveMap.remove("B");    //Removes the entry with key=b

2.3. Using LinkedCaseInsensitiveMap

The LinkedCaseInsensitiveMap class is part of the Spring Framework. Since Spring is an external Framework, it has to be added to your classpath. If we are using a Spring or Spring Boot application, it should already be available in our classpath

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>

LinkedCaseInsensitiveMap provides a case-insensitive Map implementation that wraps around the java.util.LinkedHashMap. It maintains the insertion order of the elements and preserves the case of the keys inserted, unlike Apache Common’s CaseInsensitiveMap. It does not allow null keys.

Map<String, Integer> linkedCaseInsensitiveMap = new LinkedCaseInsensitiveMap<>();

linkedCaseInsensitiveMap.put("A", 1);   //{A=1}
linkedCaseInsensitiveMap.put("B", 2);  //{A=1, B=2}
linkedCaseInsensitiveMap.put("a", 4);   //{a=4, B=2}

Note that the key “B” preserves the case. The key “a” will override the “A”. Since “a” was inserted after “B” the elements are displayed in that order.

We can call the remove on this Map using any case.

linkedCaseInsensitiveMap.remove("b");  //Case-insensitive removal

3. Conclusion

This Java tutorial explored various ways to create a case-insensitive Map. We learned the methods using TreeMap, Spring’s LinkedCaseInsensitiveMap and Apache common’s CaseInsensitiveMap.

Happy Learning!!

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode