0

我有以下情况。我在 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 程序员,所以任何人都可以解释为什么它会这样工作吗?

4

3 回答 3

8

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

name.equals(entry.getKey())

这是 Java 中的一个常见陷阱,请参阅如何比较 Java 中的字符串?等于/等于和 == 运算符之间的区别?.


顺便说一句(与您的问题无关)连接字符串时,您不需要toString()显式调用,因此:

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

可以替换为:

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

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

于 2012-06-26T06:37:53.503 回答
5

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

char* a = some_string();
char* b = some_other_string();
if (a == b) { ... }

另一方面,当您使用 比较对象时.equals(),您正在执行“结构相等”比较,这意味着您正在检查两个对象是否包含等效数据。同样,C 类似物将是:

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. 但是,即使您知道这两个变量是编译时常量,您仍然应该保持简单并使用.equals().

于 2012-06-26T06:57:11.360 回答
0

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

1)如果您使用的是 HashMap,则应该使用 map.get(key) 来检索值,而不是条目的插入器;这就是哈希映射的重点。

2)使用泛型,尽可能避免显式转换!

于 2012-06-26T07:11:41.330 回答