簡體   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