繁体   English   中英

Map containsKey返回false

[英]Map containsKey returns false

我有一个HashMap数据:

Map<CharSequence, MyObject> dataMap = GET_FROM_SOME_WHERE

dataMap有一个键是CharSequence类型,其值为“company.name”

但是下面的代码返回false

String field = "company.name";
dataMap.containsKey(field); //This return me false

我不知何故觉得这是因为我的field变量是一个String对象,而HashMap中的键是CharSequence 这就是为什么它让我失意。

如果我的猜测是正确的,那么如何摆脱它呢? 我需要上面的代码返回我的真实。 我确信关键字“company.name”在该地图数据中是关键。

Java API Spec对此主题有这样的说法:

'每个对象可以由不同的类实现,并且不能保证每个类都能够测试其实例与另一个类的实例是否相等。 因此,将任意CharSequence实例用作集合中的元素或映射中的键是不合适的。

为什么不放

CharSequence field = "company.name";

你是否将StringBuffers放入HashMap? 因为这不起作用,因为StringBuffer没有定义hashCode方法。 它从java.lang.Object继承hashCode,它使用对象的标识作为哈希码。

另一方面,String根据实际的字符串数据计算哈希码。

编辑:StringBuffer也没有实现equals()方法,所以它根本不会像人们期望的那样工作。 (new StringBuffer(“1”))。equals(new StringBuffer(“1”)) - > false。

为了实现这一点,在映射中实现CharSequence必须在检查相等性时识别String ,使用String生成相同的哈希码,并在将相等性与具有相同值的字符串进行比较时返回true (即equals应该工作来自双方)。 除非CharSequence的实现实际上是String否则这是不可能的。

解决此问题的一种方法是将Map<CharSequence,MyObject>转换为Map<String,MyObject> 迭代原始映射的入口集,并将数据放入使用String作为键的副本中,如下所示:

Map<String,MyObject> copy = new HashMap<String,MyObject>();
for (Map.Entry<CharSequence,MyObject> e : dataMap.entrySet()) {
    copy.put(e.getKey().toString(), e.getValue());
}

使用Collection有时候会非常棘手。

Map.containsKey()的工作方式是通过调用“key”对象的.equals()方法来检查对象的相等性。 因此,如果您通过StringBuffer (也实现CharSequence)将事物放入地图中,但是尝试询问密钥是否存在于地图中但是提供了String作为密钥,那么您确实在挑战集合框架。 这可以通过以下示例显示:

Map<CharSequence, Integer> dataMap = new HashMap<CharSequence, Integer>();
StringBuffer sb = new StringBuffer();
sb.append("company.name");
CharSequence cs = sb;
dataMap.put(cs, 123);

String k = "company.name";
// Below prints a 'false'
System.out.println(dataMap.containsKey(k));

因此,我的建议是始终使用相同类型的对象作为集合中的键条目(不仅仅是Map)。 在这种情况下,也许您也可以将Map定义为

Map<String, MyObject>

可能的原因是在地图中使用了equals()方法。 另一个是使用hashCode() 如果map中的键不是String,它可以通过这些方法为您提供其他值。

如果你在某个地方得到地图并且无法控制它,那么迭代按键设置似乎是唯一的方法。 否则我建议将map更改为Map<String, MyObject>

public static void main(String[] args) {
    Map<CharSequence, String> dataMap = new HashMap<>();
    dataMap.put(new StringBuilder("company.name"), "AAA");
    System.out.println(dataMap.containsKey("company.name"));
    System.out.println(mapContainsKeyNamed("company.name", dataMap));
}

static boolean mapContainsKeyNamed(String key, Map<CharSequence, ?> map) {
    for (CharSequence cs : map.keySet()) {
        if (key.equals(cs.toString())) {
            return true;
        }
    }
    return false;
}

输出:

false
true

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM