不区分大小写的字符串作为HashMap键

问题

我想使用不区分大小写的字符串作为HashMap键,原因如下。

  • 在初始化期间,我的程序使用用户定义的String创建HashMap
  • 在处理事件(在我的情况下是网络流量)时,我可能会在不同的情况下收到String但我应该能够从HashMap找到<key,value>而忽略我从流量中收到的情况。

我遵循了这种方法

CaseInsensitiveString.java

public final class CaseInsensitiveString {
            private String s;

            public CaseInsensitiveString(String s) {
                            if (s == null)
                            throw new NullPointerException();
                            this.s = s;
            }

            public boolean equals(Object o) {
                            return o instanceof CaseInsensitiveString &&
                            ((CaseInsensitiveString)o).s.equalsIgnoreCase(s);
            }

            private volatile int hashCode = 0;

            public int hashCode() {
                            if (hashCode == 0)
                            hashCode = s.toUpperCase().hashCode();

                            return hashCode;
            }

            public String toString() {
                            return s;
            }
    }

LookupCode.java

node = nodeMap.get(new CaseInsensitiveString(stringFromEvent.toString()));

因此,我正在为每个事件创建一个CaseInsensitiveString的新对象。所以,它可能会影响性能。

有没有其他方法可以解决这个问题?


#1 热门回答(229 赞)

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

这真的是你所需要的。


#2 热门回答(51 赞)

正如GuidoGarcía在their answer here中所建议的那样:

import java.util.HashMap;

public class CaseInsensitiveMap extends HashMap<String, String> {

    @Override
    public String put(String key, String value) {
       return super.put(key.toLowerCase(), value);
    }

    // not @Override because that would require the key parameter to be of type Object
    public String get(String key) {
       return super.get(key.toLowerCase());
    }
}

要么
http://commons.apache.org/proper/commons-collections/javadocs/api-release/org/apache/commons/collections4/map/CaseInsensitiveMap.html


#3 热门回答(12 赞)

一种方法是创建Apache CommonsAbstractHashedMap类的自定义子类,重写hashisEqualKeys方法以执行不区分大小写的散列和键的比较。 (注意 - 我自己从未尝试过这个......)

这样可以避免每次需要进行 Map 查找或更新时创建新对象的开销。而且常见的Map操作应该是O(1)......就像常规的HashMap一样。

如果你准备接受他们所做的实施选择,Apache CommonsCaseInsensitiveMap将为你自定义/专门化AbstractHashedMap

但是如果O(logN)getput操作是可接受的,那么带有不区分大小写的字符串比较器的aTreeMap是一个选项;例如usingString.CASE_INSENSITIVE_ORDER

如果你不介意每次执行aputorget时都创建一个新的临时String对象,那么Vishal的答案就可以了。 (虽然,我注意到如果你这样做,你就不会保留钥匙的原始情况......)