不区分大小写的Map Key Java

Cry*_*bub 1 java string hashmap case-insensitive

Map<String, Object>在其中需要String键不区分大小写

当前,我将String对象包装在Wrapper类中,该类CaseInsensitiveString的代码如下所示:

    /**
    * 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望能够使a Map<CaseInsensitiveString, Object>仍然接受a Map#get(String)并返回值而不必这样做Map#get(CaseInsensitiveString.wrap(String))。但是,在我的测试中,HashMap每当尝试执行此操作时,我都会返回null,但是如果我在调用之前包装String,它确实可以工作get()

是否可以允许我HashMap将String和CaseInsensitiveString参数同时接受到get方法并以caseInsensitive方式工作,而不管是否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")));
Run Code Online (Sandbox Code Playgroud)

并返回:

null
value
Run Code Online (Sandbox Code Playgroud)

map*_*ers 5

您可以这样做:

Map<String, Object> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
Run Code Online (Sandbox Code Playgroud)

看到这个问题

但是,请注意,如鲍里斯(Boris)在评论中所述,使用a TreeMap而不是a可能HashMap会对性能产生影响。

  • 确保OP理解这是“树”而不是哈希。因此,put是O(lg n)而不是O(1)。get也是O(lg n)而不是O(1)。因此,如果考虑到速度,这将大大降低速度。 (2认同)