【问题标题】:Is there a good way to have a Map<String, ?> get and put ignoring case? [duplicate]有没有一种好方法可以让 Map<String, ?> 忽略大小写? [复制]
【发布时间】:2010-09-17 18:34:34
【问题描述】:

有没有一个好方法可以让Map&lt;String, ?&gt; get 和 put 忽略大小写?

【问题讨论】:

标签: java map case-insensitive


【解决方案1】:

TreeMap 扩展了 Map 并支持自定义比较器。

String 提供了一个默认的不区分大小写的比较器。

所以:

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

比较器不考虑语言环境。在其 JavaDoc 中了解更多信息。

【讨论】:

  • 请注意,如果您控制正在使用的密钥而不是您的最终用户,并且您的密钥是英文的,则无需担心区域设置。
  • 如果您需要允许空值的 Map,但 TreeMap 不支持,请尝试 github.com/jdereg/java-util 的 CaseInsenstiveMap。这个在 O(1) 中访问 Map 不像 TreeMap 是 O(log n)。
【解决方案2】:

您可以使用 Apache 的 Commons Collections 中的 CaseInsensitiveMap

【讨论】:

  • 请注意 CaseInsensitiveMap is not generic,因此您不能使用 Map&lt;String, ?&gt;
  • 从 4.0 版开始,Apache 的 Commons Collections 是通用的。
【解决方案3】:

是否可以实现自己的 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 实现。

【讨论】:

  • 这基本上是 Apache 的 Commons Collections CaseInsensitiveMap 中采用的方法。
  • 在进行大写和小写操作时记得使用区域设置。
  • 不要忘记覆盖所有其他“put”方法,例如 putAll。
  • 一个奇怪的副作用是,如果你列出这张地图中的键,它们会突然变成小写。
  • 如果将其内容转移到另一个地图中,请不要忘记 containsKey 和思维问题。
【解决方案4】:

您需要一个用于 String 键的包装类,该类具有不区分大小写的 equals() 和 hashCode() 实现。使用它而不是 Map 的键的字符串。

请参阅http://www.java.happycodings.com/Java_Util_Package/code3.html 的示例实现,我在 2 分钟的谷歌搜索中找到了它。对我来说看起来很明智,虽然我从未使用过它。

【讨论】:

  • 有点棘手,不是吗?我不喜欢实现equals,并且hashCode vove all,如果它不是真的需要的话。我更喜欢创建覆盖 put 和 get 方法的 Map 实现的方法。
  • 创建一个包装类是一直在做的,一点也不难。包装类解决方案也比覆盖 put、get、putAll 更简洁。您可以在任何基于散列或等于的集合(HashSet、HashMap、ArrayList 等)上使用包装类。
  • 不同集合之间的可移植性很有趣。谢谢你。我没有考虑。我想每种方法都有其优点和缺点。
  • 使用包装类的另一个很好的理由是,如果你想保留字符串的原始大小写,那么通过 put 的覆盖是不可能做到的。
【解决方案5】:

想到的三个明显的解决方案:

  • 在使用字符串作为键之前对大小写进行规范化(非土耳其语区域设置的工作方式与世界其他地方不同)。

  • 使用设计为用作键的特殊对象类型。这是处理复合键的常用习语。

  • 将 TreeMap 与不区分大小写的 Comparator 一起使用(可能是 PRIMARY 或 SECONDARY 强度 java.text.Collat​​or)。不幸的是,Java 库没有与 hashCode/equals 等效的 Comparator。

【讨论】:

    【解决方案6】:

    您可以使用我的 Apache 许可 CaseInsensitiveMap 讨论 here。与 Apache Commons 版本不同,它保留了键的大小写。它比 TreeMap 更严格地实现了 map 契约(并且具有更好的并发语义)(详见博客 cmets)。

    【讨论】:

      【解决方案7】:

      Trove4j 可以为 HashMap 使用自定义散列。然而,鉴于无法缓存哈希码,这可能会对性能产生影响(尽管 Trove4j 可能已经找到了解决这个问题的方法?)。包装器对象(如 John M 所述)没有这种缓存缺陷。另请参阅我关于 TreeMap 的其他答案。

      【讨论】:

        【解决方案8】:

        在下面的链接中检查接受的答案。 How to check for key in a Map irrespective of the case?

        底线是“最简单的解决方案是在插入/检查之前将所有输入简单地转换为大写(或小写)。您甚至可以编写自己的地图包装器来确保一致性。”

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-19
          • 2020-07-25
          • 2011-02-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多