[英]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.