Map containsKey返回false

时间:2013-11-01 10:08:29

标签: java java-ee hashmap

我收到了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

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

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

6 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:1)

为什么不放

CharSequence field = "company.name";

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

为了实现这一点,地图中CharSequence的实现必须识别String以检查相等性,使用String生成相同的哈希码,然后返回{{当将相等性与具有相同值的字符串进行比较时(即true应该从两端起作用)。除非equals的实施实际上是CharSequence

,否则无法做到这一点

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

String

答案 4 :(得分:1)

有时使用Collection非常棘手。

Map.containsKey()的工作方式是通过调用“key”对象的.equals()方法来检查对象的相等性。所以,如果你通过 StringBuffer (也实现CharSequence)将东西放入地图中,但是试着询问地图中是否存在密钥,但是提供了 String 作为密钥,你真的在​​挑战Collections框架。 这可以通过以下示例显示:

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<String, MyObject>

答案 5 :(得分:0)

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

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