2013-08-12 110 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库(我自己并没有使用它)。

相关问题