我有以下情况.我有一个Java中的HashMap,键作为字符串.然后在某个阶段,在运行时我创建等于这些键的字符串,以便从该映射中检索数据.字符串在"for"循环中如下创建:
String keyToRetrive = "lights[" + Integer.toString(i) + "]" + ".Intensity";
Run Code Online (Sandbox Code Playgroud)
关于它的奇怪的事情,当我通过地图迭代找到等于该字符串,即使找到匹配的搜索步骤over.So在该搜索循环的关键:
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
if (name == entry.getKey()) { ///name- "lights[0].Intesity"
uniformOut = (ICleanable) entry.getValue();
break;
}
}
Run Code Online (Sandbox Code Playgroud)
具有名称"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;
}
}
Run Code Online (Sandbox Code Playgroud)
更新:在指出"=="不能正常工作并且应该使用"equals()"的事实后,我想缩小这个问题:为什么"=="适用于不是由几个创建的字符串连接块?我的意思是,如果我定义键字符串再次比较为一个简单的单个字符串:
String foo="foo";
Run Code Online (Sandbox Code Playgroud)
这样的字符串可以使用"=="与HashMap键进行比较.
我不是专业的Java程序员,所以任何人都可以解释为什么它这样工作?
您正在使用==运算符比较字符串.equals()改为使用:
name.equals(entry.getKey())
Run Code Online (Sandbox Code Playgroud)
这是Java中常见的陷阱,请参阅如何比较Java中的字符串?和等于/等于和==运算符之间的差异?.
连接字符串时BTW(与您的问题无关)您不需要toString()显式调用,因此:
"lights[" + Integer.toString(i) + "]" + ".Intensity"
Run Code Online (Sandbox Code Playgroud)
可以替换为:
"lights[" + i + "]" + ".Intensity"
Run Code Online (Sandbox Code Playgroud)
它i不仅适用于任何类型int.
当您使用比较对象时==,您正在执行"引用相等"比较,这意味着您正在检查两个引用是否指向String内存中的同一对象.如果你熟悉C,那就像是:
char* a = some_string();
char* b = some_other_string();
if (a == b) { ... }
Run Code Online (Sandbox Code Playgroud)
另一方面,当您使用比较对象时.equals(),您正在执行"结构相等"比较,这意味着您正在检查这两个对象是否包含等效数据.同样,C的类比是:
char* a = some_string();
char* b = some_other_string();
if (strcmp(a, b) == 0) { ... }
Run Code Online (Sandbox Code Playgroud)
现在,您真正不想做的事情是比较两个对象的哈希码.为什么不?因为具有相同哈希码的两个对象不一定相等!它们可能是,但你不能正确地依赖它.
更新:您还询问了为什么==适用于字符串文字.答案是因为Java编译器不在堆上分配常量字符串; 相反,它将它们存储在使用它们的类的常量池中.所以,如果你写:
String foo1 = "foo";
String foo2 = "foo";
Run Code Online (Sandbox Code Playgroud)
然后编译器将两个引用指向类的常量池中的相同位置.但是,如果你写:
String foobar1 = "foobar";
String foobar2 = "foo" + bar();
String bar() { return "bar"; }
Run Code Online (Sandbox Code Playgroud)
编译器不够聪明,无法弄清楚它foobar2在逻辑上是等价的foobar1.但是,即使您知道这两个变量是编译时常量,您仍然应该保持简单和使用.equals().
| 归档时间: |
|
| 查看次数: |
5163 次 |
| 最近记录: |