2012-10-17 64 views
2

爲了簡單起見,假設我有兩個實例HashMap<String, String>,它們共享相同的鍵。我想知道的是,它們之間存在性能和內存差異,並在Object中代表這兩個String值並將它們存儲在HashMap<String, Object>中。HashMap <String,String>和HashMap實例之間的差異<String,Object>其中Object包含兩個字符串

我的實際問題使用HashMap<String, HashSet<String>>的實例和HashMap<String, Double>的兩個實例,我希望通過合併它們,我會以某種方式節省內存,但我不確定是否會因使用自我而影響性能定義爲Object與本地對象如HashSetDouble作爲值。

+0

代碼什麼是最好的可讀性和可維護性。只有在遇到性能問題時才進行優化。 –

+0

以這種方式編碼不是類型安全的 –

回答

5

散列值是從字符串中計算出來的,所以不會有速度的影響。從長遠來看,太空影響(微小的增長)將微不足道。如果它使代碼更清晰可辨,那就去做吧,並調整性能(只要我們沒有談論巨大的性能瓶頸,那沒關係)。

速度

對於速度的影響,但要記住,HashMap<String, ?>,該String就是被散列。實際上,您可能會看到速度的小幅增加,因爲與3次查找相比,您只需執行一次查找即可找到自定義對象。

空間

對於空間的影響,記得HashMap使用一個內部數組是2的冪的大小,如果你使用的只是一個香草HashMap與像一個自定義負載因數沒有特殊的設置,那麼你可能會看到一個輕微的上升空間,因爲現在你已經(約,當然,這只是簡化):

HashSet<String>[] 
Double[] 
Double[] 

並結合之後,你就會有

CustomObject[] 
    HashSet<String> 
    Double 
    Double 

這忽略了不隨地圖一起增長的恆定大小的信息。對象佔用更多的空間,而不僅僅是對其字段的引用,但不是很多。

可讀性

自定義對象選項贏得這一個雙手向下。它的方式更乾淨,非常非常適合Java。不管表現如何,你都應該這樣做。從長遠來看,它會更好看,並且更易於維護。

例如,如果您想將字段添加到自定義對象,那很容易。但擁有單獨的地圖意味着爲更多的變量創建更多的地圖,這是骯髒的。我說去OOP的方式。

+0

+1對螺絲的性能:) – anubhava

1

如果你想將它們結合起來,創建一個類來代表他們,並有地圖者的:

public class Stuff { 
    String a; 
    String b; 
    // other fields - maybe the double you mentioned 
} 

HashMap<String, MyStuff> map; 

這肯定會節省內存,因爲你有較少的映射條目。

但是,無論如何,這是正確的方法。設計時間不是擔心微小的性能和內存影響的時候。讓你的代碼易於閱讀和使用,你的生活(和代碼)會更好。

+2

它如何節省內存?而不是hashmaps中的兩個字符串數組,您有一個包含兩個字符串的對象數組。實際上,由於物體擁有額外的空間,所以空間略有增加。 – Brian

+0

+1,這是正確的做法。特別是因爲遍歷每個映射一次散列桶的鏈表似乎很糟糕。 –

+1

@布萊恩:看到我的答案,維護重複表的開銷很大。 –

0

除非您處理大量的條目,否則差異(如果有的話)很可能不重要。它也將與平臺緊密相連(JVM版本,Java庫版本等),所以您唯一有用的答案將來自於針對每種不同方式進行分析的分析器運行。

您可能會考慮查看Guava Multimap。這可能是您的問題更清潔的解決方案。否則,我會使用自定義對象。代碼清晰度勝過每次不成熟的優化。

0

通過組合表格,你可能會在很多方面變得更好。在速度上,您只需計算散列並散列散列鏈一次而不是兩次。對於空間,只需要一個散列表而不是兩個(如果您的加載因子大約爲50%,則每個條目節省大約8個字節)和一個哈希鏈而不是兩個(每個條目約16個字節保存一個哈希鏈對象)。你需要支付你的pair對象的代價,但是最多隻有16個字節。

相關問題