2013-08-12 106 views
3

我想存儲鍵值對,其中鍵是一個整數並且值爲ArrayListsStrings減少應用程序內存佔用

我不能使用數據庫,因爲我必須使用代碼來解決特定比賽的在線問題。

對於少量的數據,我可以使用hashtables而沒有任何問題。 但是當我的數據變大時,我的堆大小就用完了。我不能更改堆大小,因爲我只需上傳代碼,而且無法提供工作環境。 這是挑戰。

+3

Map如何幫助散列表不是。 –

+0

完全錯過了。道歉。 –

+0

你可以重新設計你的解決方案來使用更少的內存嗎 – user902383

回答

-1

如果你不能增加堆大小,那麼你需要限制你的散列表(或你使用的任何其他數據結構)的大小。我建議嘗試Apache LRUMap

LRUMap

具有最大尺寸,並使用最近最少使用算法從地圖中刪除項目時 的最大尺寸是地圖的實現到達並添加新項目。

如果你真的需要一個同步的版本,那麼,這也是可供選擇:

同步版本可以得到: Collections.synchronizedMap(theMapToSynchronize)如果將 被多個線程訪問,你必須同步訪問這個 地圖。即使併發get(Object)操作也會產生不確定的 行爲。

如果你不想使用LRU鬆動,數據,那麼你需要寫一個算法,以保持在您的datastructer一些數據和休息的持久存儲諸如文件等

+0

你基本上建議他只丟棄舊數據?這對我來說似乎不是一個有效的解決方案。 – Xabster

+0

事情是我不能從地圖中刪除的東西,因爲我建立這個大地圖作爲輸入來執行操作。 –

+0

@NischalHp @NischalHp如果你不想鬆散使用LRU,那麼你需要編寫一個算法來保存一些數據在你的數據結構中,並放在持久存儲中,例如文件等。 –

0

一些想法

  1. 如果您可以寫入文件存儲在那裏的數據。你也許可以把鍵保存在內存中以加快查找速度,只需將值寫入一個文件或者每個條目甚至一個文件即可。

  2. 創建您自己的映射實現,將值列表串行化爲一個字符串或字節[],然後壓縮序列化的數據。您必須在閱讀時進行反序列化。每次你做一個get/put,你都會爲此付出很大的運行時間。一個例子見http://theplateisbad.blogspot.co.uk/2011/04/java-in-memory-compression.html

  3. 每次查找地圖數據時,只需每次計算列表值,而不是存儲它們 - 如果可以的話。

+0

我對消費的時間以及競賽有限制,並且還有足夠的時間來執行某些操作在我創建了輸入數據集之後。 我不能將它存儲到文件中,因爲我必須在線提交代碼。 –

1

使用簡單的數組而不是ArrayList可能會節省一些額外的內存(但不是很多)。

如果搜索性能不是優先級,您可以使用Pair<Integer, List<>>並手動執行搜索。

如果整數範圍是有限的,只需實例化一個數組List[integer_range]並使用數組索引作爲鍵。

由於您使用的是Strings,因此您可以嘗試使用intern(),並確保沒有重複值。

讓我們瞭解你有什麼樣的數據統計信息 - 什麼是關鍵,值是否重複自己,等等

+0

統計信息是鍵是整數,值是字符串的數組列表。 整數範圍可以從1到給定輸入字符串的長度,最多可以是5000個字符。 這些值即arraylist可以具有n * n-1個元素的大小。 –

+0

@nischalHp你確定你需要存儲數據嗎?也許你可以生成每一個需要的動態字符串?我認爲你應該自己發佈這個任務,因爲沒有它就很難幫助你。 – Dariusz

0

一個可能的優化可能是ArrayList.trimToSize從而降低由ArrayList的最小使用的存儲。

0

您可以將ArrayList存儲爲序列化(甚至可能是壓縮的)ByteBuffers。當您需要訪問列表時,您需要反序列化,更改/讀取它,然後將其存回。

操作會明顯變慢,但您可以執行一些緩存來將X Arraylist保留在堆中,並將剩餘的其餘部分存儲在其中。

3
  1. 如果經常重複字符串,請使用自然語言頻率,請勿對同一字符串使用新的對象實例。

    private Map<String, String> sharedStrings = new HashMap<>(). 
    
    public void shareString(String s) { 
        String t = sharedStrings.get(s); 
        if (t == null) { 
         t = s; 
         sharedStrings.put(t, t); 
        } 
        return t; 
    } 
    
  2. 字符串的編號可能太慢了。

  3. 將單個字符串列表(分隔符一些控制字符), 和可能的Gzip字符串(GZipOutputStream,GZipInputStream)打包​​。

  4. 用足夠的初始容量調整哈希映射。 (很抱歉,如果我狀態明顯。)

  5. 做你自己所有的ArrayList的分配,使用巨大的大String[]

    int count; 
    String[] allStrings = new String[999999]; 
    
    Map<Integer, Long> map = new HashMap<>(9999); 
    
    void put(int key, List<String> strings) { 
        int start = count; 
        for (String s : strings) { 
         allStrings[count] = s; 
         ++count; 
        } 
        // high: start index, low: size 
        long listDescriptor = (((long)start) << 32) | (count - start); 
        map.put(key, listDescriptor); 
    } 
    
  6. 有使用如int和長基元的映射實現;例如trove庫(我自己並沒有使用它)。

相關問題