我想存儲鍵值對,其中鍵是一個整數並且值爲ArrayLists
的Strings
。減少應用程序內存佔用
我不能使用數據庫,因爲我必須使用代碼來解決特定比賽的在線問題。
對於少量的數據,我可以使用hashtables而沒有任何問題。 但是當我的數據變大時,我的堆大小就用完了。我不能更改堆大小,因爲我只需上傳代碼,而且無法提供工作環境。 這是挑戰。
我想存儲鍵值對,其中鍵是一個整數並且值爲ArrayLists
的Strings
。減少應用程序內存佔用
我不能使用數據庫,因爲我必須使用代碼來解決特定比賽的在線問題。
對於少量的數據,我可以使用hashtables而沒有任何問題。 但是當我的數據變大時,我的堆大小就用完了。我不能更改堆大小,因爲我只需上傳代碼,而且無法提供工作環境。 這是挑戰。
如果你不能增加堆大小,那麼你需要限制你的散列表(或你使用的任何其他數據結構)的大小。我建議嘗試Apache LRUMap:
LRUMap
具有最大尺寸,並使用最近最少使用算法從地圖中刪除項目時 的最大尺寸是地圖的實現到達並添加新項目。
如果你真的需要一個同步的版本,那麼,這也是可供選擇:
同步版本可以得到: Collections.synchronizedMap(theMapToSynchronize)如果將 被多個線程訪問,你必須同步訪問這個 地圖。即使併發get(Object)操作也會產生不確定的 行爲。
如果你不想使用LRU鬆動,數據,那麼你需要寫一個算法,以保持在您的datastructer一些數據和休息的持久存儲諸如文件等
你基本上建議他只丟棄舊數據?這對我來說似乎不是一個有效的解決方案。 – Xabster
事情是我不能從地圖中刪除的東西,因爲我建立這個大地圖作爲輸入來執行操作。 –
@NischalHp @NischalHp如果你不想鬆散使用LRU,那麼你需要編寫一個算法來保存一些數據在你的數據結構中,並放在持久存儲中,例如文件等。 –
一些想法
如果您可以寫入文件存儲在那裏的數據。你也許可以把鍵保存在內存中以加快查找速度,只需將值寫入一個文件或者每個條目甚至一個文件即可。
創建您自己的映射實現,將值列表串行化爲一個字符串或字節[],然後壓縮序列化的數據。您必須在閱讀時進行反序列化。每次你做一個get/put,你都會爲此付出很大的運行時間。一個例子見http://theplateisbad.blogspot.co.uk/2011/04/java-in-memory-compression.html。
每次查找地圖數據時,只需每次計算列表值,而不是存儲它們 - 如果可以的話。
我對消費的時間以及競賽有限制,並且還有足夠的時間來執行某些操作在我創建了輸入數據集之後。 我不能將它存儲到文件中,因爲我必須在線提交代碼。 –
使用簡單的數組而不是ArrayList
可能會節省一些額外的內存(但不是很多)。
如果搜索性能不是優先級,您可以使用Pair<Integer, List<>>
並手動執行搜索。
如果整數範圍是有限的,只需實例化一個數組List[integer_range]
並使用數組索引作爲鍵。
由於您使用的是Strings
,因此您可以嘗試使用intern()
,並確保沒有重複值。
讓我們瞭解你有什麼樣的數據統計信息 - 什麼是關鍵,值是否重複自己,等等
統計信息是鍵是整數,值是字符串的數組列表。 整數範圍可以從1到給定輸入字符串的長度,最多可以是5000個字符。 這些值即arraylist可以具有n * n-1個元素的大小。 –
@nischalHp你確定你需要存儲數據嗎?也許你可以生成每一個需要的動態字符串?我認爲你應該自己發佈這個任務,因爲沒有它就很難幫助你。 – Dariusz
一個可能的優化可能是ArrayList.trimToSize從而降低由ArrayList的最小使用的存儲。
您可以將ArrayList存儲爲序列化(甚至可能是壓縮的)ByteBuffers。當您需要訪問列表時,您需要反序列化,更改/讀取它,然後將其存回。
操作會明顯變慢,但您可以執行一些緩存來將X Arraylist保留在堆中,並將剩餘的其餘部分存儲在其中。
如果經常重複字符串,請使用自然語言頻率,請勿對同一字符串使用新的對象實例。
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;
}
字符串的編號可能太慢了。
將單個字符串列表(分隔符一些控制字符), 和可能的Gzip字符串(GZipOutputStream,GZipInputStream)打包。
用足夠的初始容量調整哈希映射。 (很抱歉,如果我狀態明顯。)
做你自己所有的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);
}
有使用如int和長基元的映射實現;例如trove庫(我自己並沒有使用它)。
Map如何幫助散列表不是。 –
完全錯過了。道歉。 –
你可以重新設計你的解決方案來使用更少的內存嗎 – user902383