【问题标题】:Customizing the get method in HashMap [duplicate]自定义HashMap中的get方法[重复]
【发布时间】:2012-09-17 06:17:57
【问题描述】:

可能重复:
Case insensitive string as HashMap key

我有一个 Hashmap,其中一个字符串作为键,一个整数作为值。现在,我使用 get 方法来获取值,其中字符串与键值匹配。


HashMap<String,Integer> map= new HashMap<String,Integer>();
// Populate the map

System.out.println(map.get("mystring"));

我希望这个字符串比较不区分大小写。反正我能做到吗?


例如,我希望它在以下情况下返回相同的结果:


map.get("hello");
map.get("HELLO");
map.get("Hello");

【问题讨论】:

  • 在查找时可能会做 .toLowercase() 吗?

标签: java


【解决方案1】:
HashMap<InsensitiveString,Integer> map= new HashMap<>();

map.get(new InsensitiveString("mystring"));

---

public class InsensitiveString

    final String string;

    public InsensitiveString(String string)
        this.string = string;

    public int hashCode()
        calculate hash code based on lower case of chars in string

    public boolean equals(Object that)
        compare 2 strings insensitively

【讨论】:

    【解决方案2】:

    如果性能不重要,您可以使用TreeMap。下面代码的输出:

    1
    6
    6

    请注意,您要求的行为不符合Map#get contract

    更正式地说,如果此映射包含从键 k 到值 v 的映射,满足 (key==null ? k==null : key.equals(k)),则此方法返回 v;否则返回null。 (最多可以有一个这样的映射。)

    public static void main(String[] args) {
        Map<String, Integer> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
    
        map.put("hello", 3);
        map.put("HELLO", 6);
        System.out.println(map.size());
        System.out.println(map.get("heLLO"));
        System.out.println(map.get("hello"));
    }
    

    【讨论】:

    • +1 使用自定义比较器比子类更简洁。
    • 那行不通。比较器与equals()不一致,根据the docs,这是TreeMap正确实现Map接口的要求。
    • @TedHopp OP 要求的行为与String#equals 不一致。所以我看不出如何以符合 Map 合同的方式实现它(包括使用其他答案中提出的子类化/包装器选项)。
    • @TedHopp 添加了评论以澄清。
    • @TedHopp:“有序映射的行为是明确定义的,即使它的排序与 equals 不一致;它只是不遵守 Map 接口的一般约定。”这将是我的解决方案。
    【解决方案3】:

    编写一个包装器方法,将String 放在下面

    map.put(string.toLowerCase());
    

    获取方法

    map.get(string.toLowerCase());
    

    【讨论】:

      【解决方案4】:

      您可以创建一个包装类来包装 HashMap 并实现 get 和 put 方法。

      【讨论】:

        【解决方案5】:

        你可以的

        Map<String,Integer> map= new HashMap<String,Integer>() {
            @Override
            public Integer put(String key, Integer value) {
              return super.put(key.toLowerCase(), value);
            }
        
            @Override
            public Integer get(Object o) {
               return super.get(o.toString().toLowerCase());
            }
        };
        

        【讨论】:

        • 您还需要将put 覆盖为小写所有键。否则,您永远无法检索存储在非小写键下的值。您可能还必须处理putAll 和将另一个地图作为参数的构造函数。
        • 我知道您正在查找查询字符串的小写字母,但是如果从未插入小写版本怎么办?
        • 添加了 put 但未添加 contains 以及您可能需要的其他一些内容。
        • 包装类可能是比子类化更好的方法。这是处理那些“其他人”的更简单的方法。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-16
        • 2013-03-06
        • 2014-07-17
        • 2016-06-02
        • 2011-10-07
        • 2015-05-18
        相关资源
        最近更新 更多