簡體   English   中英

在 java 中使用 HashMap 中的 char[] 數組

[英]Using char[] array in HashMap in java

我正在使用 HashMap 和一個 char 數組作為鍵。 但是當我將鍵值放入 HashMap 並打印它時,作為鍵打印的值是一些奇怪的值。 如果我改用字符串,它工作正常。 請讓我知道如何使這項工作適用於 char[] 值。

            while((ch = br.read()) != -1) {
            s = new char[10];
            s[i++] = (char)ch;

            while( (i < 10) && ((ch = br.read()) != -1)) {
                s[i++] = (char)ch;                  
            }

            //System.out.println(s);
            hmap.put(s, 1); 
            //System.out.println(hmap);
            i = 0;              
        }

鍵:BZOUA1578L 值:1

hashmap 中的內容是 {[C@31ff23=1} 而不是 {BZOUA1578L, 1}

我有大量 GB 的數據要讀取,如果我使用 String,我的堆大小就用完了。

那你就得想別的辦法了。

  • 您可以考慮使用帶有自定義ComparatorTreeMap<char[], V> ...但這是權宜之計。

  • 您可以實現自定義 hash 基於表的Map class 使用char[]作為鍵,但不使用鍵equals(Object)的方法和hashcode()碼進行數組哈希和相等測試。 這也是權宜之計。

  • 你可以買一台更大的機器……另一個權宜之計。

  • 您可以重新設計算法,這樣它就不必將所有數據放入一個 Java 程序的地址空間中的大型內存 hash 表中。

您當前正在做的事情無法擴展。 即使您設法使用char[]鍵而不是String鍵來實現 map,您可能只會將用於保存鍵的空間減少一半。 這將給您帶來的最大好處是能夠處理大約兩倍於您當前可以處理的鍵的數量。 然后你又撞牆了。

從長遠來看,如果您想繼續擴大規模,最后一個選項是最好的。


順便說一句,@Sean Patrick Floyd 建議對關鍵字符串進行實習可能只會讓事情變得更糟。 首先,在同一個 map 中,您永遠不會得到相等但不是 == 的字符串作為鍵。 所以實習並不能節省任何東西。 其次,interning是使用私有的hash表進行的,JVM需要分配空間來表示這個表。

唯一可能值得實習的情況是,如果您用來執行 map 查找的字符串可能會在多個 GC 循環中存活下來。 只有這樣,實習才能節省空間。


最后,有一種情況可能會導致您的密鑰字符串使用的 memory 比您意識到的要多得多。 考慮一下:

BufferedReader br = ...
Map<String, Value> map = new HashMap<String, Value>();

String line;
while ((line = br.readLine()) != null) {
    ...
    String key = line.substring(...);
    map.put(key, ...);
}

問題是substring方法與原始字符串共享相同的支持char[] 如果key是長壽命的(它可能會是長壽命的),這意味着原始的大型后備數組也將是長壽命的,即使我們只會通過key object 引用該數組的一部分。

解決方案是這樣寫:

    String key = new String(line.substring(...));

這會強制將字符復制到一個新的(較小的)字符數組中。

更新- 在 Java 7 中對java.lang.String實施的更改解決了這個問題。 substring方法現在會復制后備數組的相關切片。

那是因為 arrays 沒有 toString() 方法。 你看到的是Object.toString()的Output:

return getClass().getName() + "@" + Integer.toHexString(hashCode());

在你的情況下:

[C     = internal name of char[].class
@      = "@"
31ff23 = your array's identity hash code as hey String
=1     = the value

順便說一句,他們也沒有 hashCode() 實現,因此他們為 HashMaps 制作了錯誤的鍵(請參閱有關使用字節 arrays 作為 HashMap 鍵的類似問題)。

打印是您最不關心的問題,真的。 真正的問題是 char[] 沒有有意義地實現HashMap依賴的equals()hashCode()方法。 Therefore the map will not recognize different arrays with the same content as the same keys, which in all probablity defeats your purpose of using a hash map in the first place.

因此,您需要將 arrays 包裝在具有equals()hashCode()的東西中。 我可以建議將它們包裝在java.lang.String中嗎?

char[].toString()方法(在打印 map 內容時使用)未實現以顯示數組的內容 - 它使用默認的toString()實現,其中包括 class 名稱(在這種情況下為[C )后跟哈希碼,通常是 JVM 中的(十六進制)memory 地址

您不應該使用 arrays 作為HashMap中的鍵,因為它們沒有基於元素實現hashCode()equals() 首選String

您嘗試使用字符數組作為鍵,它只是一個 Object 參考,它只是一個哈希碼

從 map 獲取數據時您可能沒有給出的值。 所以使用 Char[] 數組元素,

您可以跟蹤它,以便稍后獲取數據..

不可能對 char arrays 進行這項工作,因為HashMap基於關鍵對象的hashCode()equals()方法。 並且 arrays 繼承了Object的實現,它基於身份而不是內容 - 你也不能覆蓋它們。 What you see as the "contents" of the map is the output of toString() , which for arrays is also based on object identity rather than contet.

使用字符串,這就是它們的用途。 幾乎所有的 Java API 都設計用於字符串,而很少直接使用 char arrays。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM