【问题标题】:CaseInsensitive Map Key Java [duplicate]不区分大小写的映射键 Java [重复]
【发布时间】:2016-12-25 20:33:22
【问题描述】:

我有一个Map<String, Object>,其中我需要字符串键不区分大小写

目前我正在将我的 String 对象包装在一个名为 CaseInsensitiveString 的 Wrapper 类中,其代码如下所示:

    /**
    * A string wrapper that makes .equals a caseInsensitive match
    * <p>
    *     a collection that wraps a String mapping in CaseInsensitiveStrings will still accept a String but will now
    *     return a caseInsensitive match rather than a caseSensitive one
    * </p>
    */
public class CaseInsensitiveString {
    String str;

    private CaseInsensitiveString(String str) {
        this.str = str;
    }

    public static CaseInsensitiveString wrap(String str) {
        return new CaseInsensitiveString(str);
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null) return false;

        if(o.getClass() == getClass()) { //is another CaseInsensitiveString
            CaseInsensitiveString that = (CaseInsensitiveString) o;
            return (str != null) ? str.equalsIgnoreCase(that.str) : that.str == null;
        } else if (o.getClass() == String.class){ //is just a regular String
            String that = (String) o;
            return str.equalsIgnoreCase(that);
        } else {
        return false;
        }

    }

    @Override
    public int hashCode() {
        return (str != null) ? str.toUpperCase().hashCode() : 0;
    }

    @Override
    public String toString() {
        return str;
    }
}

我希望能够获得 Map&lt;CaseInsensitiveString, Object&gt; 以仍然接受 Map#get(String) 并返回值而无需执行 Map#get(CaseInsensitiveString.wrap(String))。然而,在我的测试中,每当我尝试执行此操作时,我的HashMap 都会返回 null,但如果我在调用 get() 之前包装字符串,它确实有效

是否可以让我的HashMap 接受字符串和CaseInsensitiveString 参数到get 方法并以不区分大小写的方式工作,无论String 是否被包装,如果是,我是什么做错了吗?

作为参考,我的测试代码如下所示:

    Map<CaseInsensitiveString, String> test = new HashMap<>();
    test.put(CaseInsensitiveString.wrap("TesT"), "value");
    System.out.println(test.get("test"));
    System.out.println(test.get(CaseInsensitiveString.wrap("test")));

然后返回:

null
value

【问题讨论】:

  • 根据你想要的,主要是速度方面的考虑,你可以使用TreeMapString.CASE_INSENSITIVE_ORDER
  • 简单地扩展您自己的地图并在放置和获取时将字符串转换为大写/小写并不能解决问题?
  • 您可以将所有键存储为小写(或大写)。在查询之前,将查询字符串转换为小写。
  • 那些转换为大写/小写的解决方案在这里可能是可行的,但是我正在处理使用 CasePreservation 的外部 api 的接口,我希望尽可能保持这一点跨度>

标签: java string hashmap case-insensitive


【解决方案1】:

你可以这样做:

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

this question

但是,请注意使用 TreeMap 而不是 HashMap 的性能影响,正如 Boris 在 cmets 中提到的那样。

【讨论】:

  • 如果您认为这是重复的,那么原因很密切。请标记(或在您有足够声誉后投票)以关闭。
  • @SotiriosDelimanolis 我没有意识到我有权标记问题,谢谢!
  • 太完美了!并感谢您的链接,抱歉我之前没有找到它:)
  • @CrypticCabub 很高兴为您提供帮助!是的,也许下次在发布问题之前尝试做更多的谷歌搜索,但这次不用担心!
  • 确保 OP 明白这是一个 tree 而不是哈希。所以putO(lg n) 而不是O(1)get 也是 O(lg n) 而不是 O(1)。所以如果速度是一个问题,这会明显变慢。
【解决方案2】:

这是预期的:

看到这个:

Map<CaseInsensitiveString, String> test = new HashMap<>();

这一行告诉 MAP 只接受 CaseInsensitiveString 对象,当您将另一个对象传递给映射时,它会将其视为未知键并返回 null。

您可以通过将其更改为:

Map<Object, String> test = new HashMap<>();

【讨论】:

    猜你喜欢
    • 2019-10-04
    • 2020-07-13
    • 2012-09-22
    • 1970-01-01
    • 2017-07-19
    • 2018-08-31
    • 2017-01-27
    • 2015-03-17
    • 1970-01-01
    相关资源
    最近更新 更多