有没有一个好方法可以Map<String, ?>
忽略大小写?
8 回答
TreeMap 扩展了 Map 并支持自定义比较器。
String 提供了一个默认的不区分大小写的比较器。
所以:
final Map<String, ...> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
比较器不考虑语言环境。在其 JavaDoc 中阅读有关它的更多信息。
您可以使用Apache 的 Commons Collections 中的CaseInsensitiveMap。
是否可以实现自己的 Map 覆盖 put/get 方法?
public class CaseInsensitiveMap extends HashMap<String, String> {
...
put(String key, String value) {
super.put(key.toLowerCase(), value);
}
get(String key) {
super.get(key.toLowercase());
}
}
这种方法不会强迫您更改“键”类型,而是您的 Map 实现。
您需要一个带有不区分大小写的 equals() 和 hashCode() 实现的 String 键的包装类。使用它而不是 Map 的键的字符串。
请参阅http://www.java.happycodings.com/Java_Util_Package/code3.html上的示例实现, 我在 2 分钟的谷歌搜索中找到了它。对我来说看起来很明智,虽然我从未使用过它。
想到的三个明显的解决方案:
在使用字符串作为键之前对大小写进行规范化(不是土耳其语区域设置与世界其他地方的工作方式不同)。
使用设计用作键的特殊对象类型。这是处理复合键的常用习语。
将 TreeMap 与不区分大小写的 Comparator 一起使用(可能是 PRIMARY 或 SECONDARY 强度 java.text.Collator)。不幸的是,Java 库没有与 hashCode/equals 等效的比较器。
您可以使用此处讨论的我的 Apache 许可CaseInsensitiveMap。与 Apache Commons 版本不同,它保留了键的大小写。它比 TreeMap 更严格地实现了 map 契约(加上具有更好的并发语义)(详见博客评论)。
Trove4j可以为 HashMap 使用自定义散列。然而,鉴于无法缓存哈希码,这可能会对性能产生影响(尽管 Trove4j 可能已经找到了解决这个问题的方法?)。包装器对象(如 John M 所述)没有这种缓存缺陷。另请参阅我关于 TreeMap 的其他答案。
在下面的链接中检查接受的答案。 无论情况如何,如何检查 Map 中的密钥?
底线是“最简单的解决方案是在插入/检查之前简单地将所有输入转换为大写(或小写)。您甚至可以编写自己的地图包装器来确保一致性。”