针对字符串的Java HashMap键比较失败

时间:2012-06-26 06:36:08

标签: java

我有以下情况。我有一个Java中的HashMap,键作为字符串。 然后在某个阶段,在运行时我创建等于这些键的字符串,以便从该映射中检索数据。字符串在“for”循环中创建如下:

 String keyToRetrive = "lights[" + Integer.toString(i) + "]" + ".Intensity";

奇怪之处在于,当我遍历地图找到等于该字符串的键时,即使找到匹配项,搜索步骤也会结束。所以在此搜索循环中:

  while (iter.hasNext()) {
        Map.Entry entry = (Map.Entry) iter.next();
        if (name == entry.getKey()) {  ///name- "lights[0].Intesity"
            uniformOut = (ICleanable) entry.getValue();
            break;
        }
    }

名称为“lights [0] .Intesity”的键永远不会返回true,即使地图包含一个。我如何解决它。我使用了hashCode()来比较两个字符串值。所以这个版本确实有效:

 while (iter.hasNext()) {
        Map.Entry entry = (Map.Entry) iter.next();
        if (name.hashCode() == entry.getKey().hashCode()) {
            uniformOut = (ICleanable) entry.getValue();
            break;
        }
    }

更新:在指出“==”不能正常工作并且应该使用“equals()”的事实后,我想缩小这个问题:为什么“==”对于不是的字符串有效从几个连接块创建?我的意思是,如果我定义键字符串以将其再次比较为简单的单个字符串:

 String foo="foo";

这样的字符串可以使用“==”与HashMap键进行比较。

我不是专业的Java程序员,所以任何人都可以解释为什么它会这样运作?

3 个答案:

答案 0 :(得分:8)

您正在使用==运算符比较字符串。请改用equals()

name.equals(entry.getKey())

这是Java中常见的陷阱,请参阅How do I compare strings in Java?Difference between Equals/equals and == operator?


在连接字符串时BTW(与您的问题无关),您不需要明确调用toString(),所以:

"lights[" + Integer.toString(i) + "]" + ".Intensity"

可以替换为:

"lights[" + i + "]" + ".Intensity"

它适用于任何类型的i,而不仅仅是int

答案 1 :(得分:5)

使用==比较对象时,您正在执行“引用相等”比较,这意味着您正在检查两个引用是否指向同一个{ {1}}内存中的对象。如果你熟悉C,那就像是:

String

另一方面,当您使用char* a = some_string(); char* b = some_other_string(); if (a == b) { ... } 比较对象时,您正在执行“结构相等”比较,这意味着您正在检查这两个对象是否包含等效数据。同样,C的类比是:

.equals()

现在,你真的,真的不想做的事情是比较两个对象的哈希码。为什么不?因为具有相同哈希码的两个对象不一定相等!它们可能是,但你不能正确地依赖它。


更新:您还询问了char* a = some_string(); char* b = some_other_string(); if (strcmp(a, b) == 0) { ... } 为什么适用于字符串文字。答案是因为Java编译器不在堆上分配常量字符串;相反,它将它们存储在使用它们的类的常量池中。所以,如果你写:

==

然后编译器将两个引用指向类的常量池中的相同位置。但是,如果你写:

String foo1 = "foo";
String foo2 = "foo";

编译器不够聪明,无法确定String foobar1 = "foobar"; String foobar2 = "foo" + bar(); String bar() { return "bar"; } 在逻辑上等同于foobar2。但是,即使您知道这两个变量是编译时常量,仍然应该保持简单并使用foobar1

答案 2 :(得分:0)

其他人已经说明了为什么你的代码不起作用,但是:

1)如果你正在使用HashMap,你应该使用map.get(key)来检索值,而不是条目的交互者;这就是哈希地图的重点。

2)使用泛型,避免尽可能多地明确施放!