我想存储键值对,其中键是一个整数并且值为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