繁体   English   中英

Java HashMap密钥与字符串的比较失败

[英]Java HashMap key comparison against string fails

我有以下情况。 我在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专家,所以有人可以解释为什么这样做吗?

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

name.equals(entry.getKey())

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


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

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

可以替换为:

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

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

当使用==比较对象时,您将执行“引用相等”比较,这意味着您正在检查两个引用是否指向内存中的同一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()

其他人已经说明了为什么您的代码无法正常工作,但是:

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

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

暂无
暂无

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

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