2

I want to access java.util.HashMap without considering case of the key.

By this, I mean, if I add following entry to my HashMap:

java.util.HashMap<String, Object> myMap = new java.util.HashMap<String, Object>();
myMap.put("foo", new Foo());  // Note lower-case key used here

Then I should be able to get Foo object by following code:

Foo f = (Foo) myMap.get("FOO"); // Note UPPER-case key used here

Is this possible?

Thanks.

2
  • Note that it is not meaningful to talk about case without considering the locale. The lower form of I can be i or ı depending on the configuration of the underlying operating system. Commented Feb 5, 2013 at 9:18
  • Related: Java: Collection RemoveAll Ignoring Case? Commented Feb 5, 2013 at 9:21

7 Answers 7

10
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class TestEnum {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Map<String, String> oldMap = new HashMap<String, String>();
        oldMap.put("akshay", "Lokur");
        oldMap.put("sumiT", "BORhade");

        Map<String, String> newMap = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
        newMap.putAll(oldMap);
        String value = newMap.get("AKShay");
        System.out.println(value);
    }

}
Sign up to request clarification or add additional context in comments.

2 Comments

From the documentation: Note that the ordering maintained by a tree map, like any sorted map, and whether or not an explicit comparator is provided, must be consistent with equals if this sorted map is to correctly implement the Map interface. The class contract is being violated.
Going off @McDowell, would you be able to easily predict what would happen when you ran newMap.get("foo") after oldMap.put("foO", "bar1"); oldMap.put("fOo", "bar2");?
4

Subclass the HashMap to use your own "MyIgnoreCaseHashMap":

public class MyIgnoreCaseHashMap extends HashMap<String, Object> {

    Object get(String key) {
       return super.get(key.toLowercase());
    }

    void put(String key, Object value) {
       super.put(key.toLowerCase(), value);
    }
}

This handles the keys always in their lowercase version. Also, consider to override the methods that may use keys, like containsKey.

And if you don't mind include external libraries, the apache-commons has the CaseInsensitiveMap class to revolve your problem

2 Comments

This is the only solution to OP's problem. You can also add why the original wouldn't work.
This really is the obvious solution!
1

I am not sure why you need this:

But consider adding to myMap like

myMap.put("foo".toLowerCase(), new Foo());

and retrieving like

Foo f = (Foo) myMap.get("FOO".toLowerCase());

2 Comments

This is not the answer to the question. It's quite clear that, OP don't know in what form is the key in the Hashmap, and that is why he's concerned. If he could do this, he wouldn't have asked.
@RohitJain, it is not very clear from the question itself. I can see some new comments by OP, but he says he add there by himself. So why not modifying code like this?
1

Simple solution is to just convert all keys to upper case before use like this:

myMap.put (key.toUpperCase (), value);
String value = myMap.get (anotherKey.toUpperCase ());

Comments

0

You can do this, by transforming the key to capital letters before pushing / retrieving the object to the map. Like:

myMap.put("foo".toUpperCase(), new Foo());

Foo f = myMap.get("foo".toUpperCase());

Or

myMap.put("foo".toLowerCase(), new Foo());

Foo f = myMap.get("foo".toLowerCase());

2 Comments

Then it is a bit more tricky. If you are sure that uppercase and lower case is the same, you can try two gets (one with "foo".toUpperCase() and one with "foo".toLowerCase() A simple if will tell you which key contains a value or if both don't contain one. Of course it will be difficult if both keys retrieve a value :)
Since you have no control over puts to the map, there is no way to change the case OR wrapping the string object with another object providing the hash of string.toLowerCase(). Consider re-creating the map with altered keys.
0

If you don't want to repeatedly use "toLowerCase" whenever you're using your map, you could create your own subclass of HashMap for this purpose. Override get, put, containsKey, and remove to convert the key to lowercase, and then call the appropriate function with this lowercase key in the superclass.

Note that toLowerCase()/toUpperCase() behave differently depending on locale, so there is a risk that you will get different results simply based on where the JVM is running. This may or may not be desirable depending on what strings you are using as keys (user-entered, hardcoded, etc). Consider toUpperCase(Locale locale) if you need consistent casing rules.

Comments

0

For a fully fleshed out example take a look at the Apache Commons db utils... specifically, source the the private inner class org.apache.commons.dbutils.BasicRowProcessor$CaseInsensitiveHashMap

https://apache.googlesource.com/commons-dbutils/+/trunk/src/main/java/org/apache/commons/dbutils/BasicRowProcessor.java

This is used in some JDBC drivers to access maps that are the result queries in case-insensitive column-name databases like Oracle.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.