Case Insensitive String as Hashmap Key

How to ignore the case sensitive when we look for a key in the Map?

Why not use a TreeMap instead of HashMap, then you could specify a Comparator with a case insensitive order (String.CASE_INSENSITIVE_ORDER):

public static void main(String[] args) throws Exception {

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

lookup.put("One", 1);
lookup.put("tWo", 2);
lookup.put("thrEE", 3);

System.out.println(lookup.get("Two"));
System.out.println(lookup.get("three"));
}

Outputs:

2
3

CaseInsensitive Map Key Java

You can do it like this:

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

See this question.

However, note the performance implications of using a TreeMap instead of a HashMap, as mentioned by Boris in the comments.

Is there any efficient way to have a case insensitive string as a HashMap key?

The easiest way to do it is to use UniCase as a key:

use unicase::UniCase;

type Words = std::collections::HashMap<UniCase, u32>;

If I understand their documentation, UniCase::new("The") stores the actual string "The" in it, but if you compare it with Unicase::new("the"), you will see that it is the same string.

How to check for key in a Map irrespective of the case?

Not with conventional maps.

"abc" is a distinct string from "ABC", their hashcodes are different and their equals() methods will return false with respect to each other.

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.

If you want to maintain the case of the key as provided, but with case-insensitive comparison, you could look into using a TreeMap and supplying your own Comparator that will compare case-insensitively. However, think hard before going down this route as you will end up with some irreconcilable inconsistencies - if someone calls map.put("abc", 1) then map.put("ABC", 2), what case is the key stored in the map? Can you even make this make sense? Are you comfortable with the fact that if someone wraps your map in a standard e.g. HashMap you'll lose functionality? Or that if someone happens to be iterating through your keyset anyway, and does their own quick "contains" check by using equals() you'll get inconsistent results? There will be lots of other cases like this too. Note that you're violating the contract of Map by doing this (as key equality is defined in terms of the equals() method on the keys) so it's really not workable in any sense.

Maintaining a strict uppercase map is much easier to work with and maintain, and has the advantage of actually being a legal Map implementation.

Ignore case while comparing string with keyvalue in the hashmap

If you see the implementation of HashMap getKey method you have to pass the proper key to generate the hash value and get the actual value from that bucket.

    if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;

Three solutions

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

OR

    Map<String, String> map = new CaseInsensitiveMap<String, String>();

OR

    Looping through map with the ignore case

Map with case insensitive get, remove and containsKey

You can't do that with HashMap. Use a TreeMap instead:

new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER)

For highly concurrent version, use ConcurrentSkipListMap:

new ConcurrentSkipListMap<String, String>(String.CASE_INSENSITIVE_ORDER)

Since you don't care about actual ordering, the String.CASE_INSENSITIVE_ORDER is fine for this. If locale-sensitive ordering is required, you need to supply a Collator instead, e.g.

Collator.getInstance(Locale.forLanguageTag("es-ES"))

Case Insensitive map in Java

You can convert the strings into lower case while putting into the map.

Map<String, Integer> map = new LinkedHashMap<>();
for (String w : data) {
Integer n = map.get(w.toLowerCase());
n = (n == null) ? 1 : ++n;
map.put(w.toLowerCase(), n);
}
System.out.println(map);

Case insensitive key for hashmap kotlin?

For this, you would need either to provide some extension function that would put and get the entry in some defined way (e.g. using every time lowercase() String's method) keeping keys case insensitive

fun HashMap<String, Int>.putInsensitive(k: String, v: Int) {
this[k.lowercase()] = v
}

fun HashMap<String, Int>.getInsensitive(k: String, v: Int): Int? = this[k.lowercase()]

or provide your own Map interface implementation (it could even inherit from HashMap)

class InsensitiveHashMap<V> : HashMap<String, V>() {
override fun put(key: String, value: V): V? = super.put(key.lowercase(), value)

override fun get(key: String): V? = return super.get(key.lowercase())
}

Case insensitive hashmap for strings in java

Simple fix;

CaseInsensitiveMap stuff = new CaseInsensitiveMap();

prints out;

{happy=11}
11
{happy=11}

CaseInsensitiveMap is extending HashMap<String, Integer> so it is a subclass of it, the fact that you reference stuff as HashMap (as the superclass) allows it to use default get method. You can even see in an IDE that your custom get(String) in CaseInsensitiveMap is not even used.

Only overridden methods will be used if you use superclass reference for a subclass, as you've done in your code. That is why only your custom put(String, Integer) method works since it is overriding the method in super.

Referencing Subclass objects with Subclass vs Superclass reference for more info on that issue.



Related Topics



Leave a reply



Submit