不区分大小写的字符串作为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());
}
}
#3 热门回答(12 赞)
一种方法是创建Apache CommonsAbstractHashedMap
类的自定义子类,重写hash
和isEqualKeys
方法以执行不区分大小写的散列和键的比较。 (注意 - 我自己从未尝试过这个......)
这样可以避免每次需要进行 Map 查找或更新时创建新对象的开销。而且常见的Map
操作应该是O(1)......就像常规的HashMap
一样。
如果你准备接受他们所做的实施选择,Apache CommonsCaseInsensitiveMap
将为你自定义/专门化AbstractHashedMap
。
但是如果O(logN)get
和put
操作是可接受的,那么带有不区分大小写的字符串比较器的aTreeMap
是一个选项;例如usingString.CASE_INSENSITIVE_ORDER
。
如果你不介意每次执行aput
orget
时都创建一个新的临时String对象,那么Vishal的答案就可以了。 (虽然,我注意到如果你这样做,你就不会保留钥匙的原始情况......)