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