2012-11-11 58 views
5

我想用Java(儘可能少的內存和儘可能快的訪問)有效地加載大型CSV格式的文件(通常爲200-600mb)。目前,該程序正在使用一串字符串列表。此操作之前是通過一個Lua程序處理的,每個CSV行使用一個表格來保存每個「行」表格。Java - 如何有效地存儲大量的字符串數組

下面是對存儲器的差異和加載時間的示例:

  • CSV文件 - 232mb
  • 的Lua - 549mb在存儲器 - 157秒加載
  • 爪哇 - 1,378mb在存儲器 - 12加載的秒數

如果我沒記錯的話,Lua表中的重複項存在作爲對實際值的引用。我懷疑在Java的例子中,List持有每個重複值的單獨副本,這可能與更大的內存使用有關。

下面是CSV文件內的數據的一些背景:

  • 每個字段包括一字符串的
  • 每行內的特定字段可以包括一組字符串(例如,字段中的一個3可以是「紅」,「綠」或「藍」)。
  • 還有很多重複內容中的字符串。

下面是什麼,可能需要加載的數據的一些例子:

  • 搜索通過試圖匹配給定的字符串,返回匹配的字符串在GUI
  • 顯示匹配的所有字符串表(可通過字段排序)。
  • 改變或替換字符串。

我的問題 - 是否有一個需要更少的內存來保存數據,但仍然提供功能,以方便,快速地搜索/排序數據的集合?

+1

如果你知道該列3只持有少數可能的值,你可以[實習生他們(http://docs.oracle .com/javase/7/docs/api/java/lang/String.html#intern%28%29)以減少內存使用量。另請參閱:http://stackoverflow.com/a/1855195/829571 – assylias

+0

感謝assylias我將運行一些測試使用它。你知道它是否對短字符串有效 - 例如「去」或「去」。大多數字段包含45個字符的字符串,但有些字符串很短(4個或更少)。 – user1816198

+2

看看http://stackoverflow.com/questions/12792942/alternatives-to-java-string-interning –

回答

0

也許這篇文章能有一定的幫助:

http://www.javamex.com/tutorials/memory/string_saving_memory.shtml

+0

謝謝 - 非常有用的信息。 – user1816198

+1

我最終嘗試了通過文章介紹的兩個例子。事實證明,intern()保存的內存最多。我會繼續嘗試(特別是在我完成了更多項目之後),但這確實使我的內存使用與Lua一致,儘管載入時間更快。 – user1816198

+0

這就是爲什麼你不應該做鏈接的答案 - 鏈接現在已經死了。 –

0

爲了優化你的內存問題,我建議使用Flyweight模式,特別是對於有很多重複的字段。您可以使用TreeSetTreeMap

如果你給一個很好的實現你的LineItem類(實現equalshashcodeComparable),您可以優化內存使用了很多。

0

DAWG

有向非循環詞圖是存儲字的最有效方式(最佳爲內存消耗反正)。

但可能過度殺傷這裏,正如其他人所說不創建重複只是對同一個實例進行多次引用。

+0

謝謝我會再看看這個選項。我不會考慮任何有害的東西 - 這樣做的效率越高,每次會話可以加載的數據越多,對最終用戶來說也更好。 – user1816198

0

就像一個方面說明。

對於你懷疑的重複字符串數據,你不需要擔心,因爲java本身關心的是所有字符串都是最終的,並且所有引用都以內存中的同一對象爲目標。

所以不知道怎麼盧阿在做的工作,但在java中應該也相當有效率

+0

但是,如果這是真的,等於根本就沒有必要,==會比較工作 – Igor

+0

好吧,equals是正確的方式,因爲它是你應該比較java中的對象的方式,==也可以工作,但它只是一種因爲JVM內部處理字符串的方式 –

+0

嗯,我不確定有多少內存java虛擬內部持有字符串引用,但我很確定,在足夠大的程序==不會工作 – Igor

1

一個簡單的解決方案。你可以有一些HashMap是你會提到所有的唯一字符串。 而在ArrayList中,您只需參考HashMap中的現有唯一字符串。

喜歡的東西:

private HashMap<String, String> hashMap = new HashMap<String, String>(); 

public String getUniqueString(String ns) { 
    String oldValue = hashMap.get(ns); 
    if (oldValue != null) { //I suppose there will be no null strings inside csv 
    return oldValue; 
    }   
    hashMap.put(ns, ns); 
    return ns; 
} 

簡單的用法:

List<String> s = Arrays.asList("Pera", "Zdera", "Pera", "Kobac", "Pera", "Zdera", "rus"); 
List<String> finS = new ArrayList<String>(); 
for (String er : s) { 
    String ns = a.getUniqueString(er); 
    finS.add(ns); 
} 
+0

聲音就像你試圖優化已經被java優化的東西(爲內存中的重複字符串保存內存),不需要這樣的實現,請參閱我的答案 –

相關問題