CrypticCabub CrypticCabub - 3 months ago 7
Java Question

CaseInsensitive Map Key Java

I have a

Map<String, Object>
in which I need the String key to be case insensitive

Currently I am wrapping my
String
objects in a Wrapper class I've called
CaseInsensitiveString
the code for which looks like this:

/**
* A string wrapper that makes .equals a caseInsensitive match
* <p>
* a collection that wraps a String mapping in CaseInsensitiveStrings will still accept a String but will now
* return a caseInsensitive match rather than a caseSensitive one
* </p>
*/
public class CaseInsensitiveString {
String str;

private CaseInsensitiveString(String str) {
this.str = str;
}

public static CaseInsensitiveString wrap(String str) {
return new CaseInsensitiveString(str);
}


@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;

if(o.getClass() == getClass()) { //is another CaseInsensitiveString
CaseInsensitiveString that = (CaseInsensitiveString) o;
return (str != null) ? str.equalsIgnoreCase(that.str) : that.str == null;
} else if (o.getClass() == String.class){ //is just a regular String
String that = (String) o;
return str.equalsIgnoreCase(that);
} else {
return false;
}

}

@Override
public int hashCode() {
return (str != null) ? str.toUpperCase().hashCode() : 0;
}

@Override
public String toString() {
return str;
}
}


I was hoping to be able to get a
Map<CaseInsensitiveString, Object>
to still accept a
Map#get(String)
and return the value without having to do
Map#get(CaseInsensitiveString.wrap(String))
. In my testing however, my
HashMap
has returned null whenever I have tried to do this but it does work if I wrap the String before calling
get()


Is it possible to allow my
HashMap
to accept both String and
CaseInsensitiveString
parameters to the get method and work in a caseInsensitive fashion regardless of if the
String
is wrapped or not, and if so, what am I doing wrong?

for reference my test code looks like this:

Map<CaseInsensitiveString, String> test = new HashMap<>();
test.put(CaseInsensitiveString.wrap("TesT"), "value");
System.out.println(test.get("test"));
System.out.println(test.get(CaseInsensitiveString.wrap("test")));


and returns:

null
value

Answer

You can do it like this:

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

See this question.