适用于Android的内存友好型快速键值访问解决方案

时间:2012-05-15 21:03:38

标签: java android database memory map

我有一个Android应用程序,它遍历数千个整数的数组,并使用它们作为键值来访问整数对(让我们称它们为id),以便用它们进行计算。它需要尽可能快地完成,最后返回一个对应用程序至关重要的结果。

我尝试将HashMap加载到内存中以快速访问这些数字,但这导致了OOM异常。我也尝试将这些id写入RandomAccessFile并将它们的偏移量存储在另一个HashMap上,但速度太慢了。此外,仅存储偏移量的新HashMap仍占用大量内存。

现在我正在考虑SQLite,但我不确定它是否会更快。是否有任何结构或库可以帮助我?

编辑:密钥数量超过2000万,而我只需要访问数千个密钥。我不知道我将事先访问哪些,因为它随用户输入而变化。

3 个答案:

答案 0 :(得分:4)

您可以使用Trove的TIntLongHashMap将原始int映射到原始long s(存储值对的int s)。这样可以节省普通香草Map的对象开销,这会迫使您使用包装器类型。

修改

由于您的更新声明您有超过2000万个映射,因此可能会有更多节省空间的结构而不是哈希映射。将密钥划分为桶的方法,结合一些子密钥压缩,即使是最有效的哈希映射实现,也可以节省一半的内存。

答案 1 :(得分:1)

SQLite是一个嵌入式关系数据库,它使用索引。我敢打赌它比使用RandomAccessFile快得多。你可以尝试一下。

答案 2 :(得分:1)

我的建议是重新排列Buckets中的密钥 - 我的意思是识别(或多或少)密钥的分布,然后创建与每个密钥范围相对应的文件(关键是每个文件必须包含那些可以进入内存的整数,然后当你搜索一个密钥时,你只需将整个文件读入内存并查找它。

例如,假设密钥的分布是统一的,存储500k值对应0-500k密钥值,500k值对应500k-1mil密钥等等......

编辑:如果你尝试过这种方法,但它仍然很慢,我仍然有一些技巧:

  1. 首先确保你的师在所有桶之间实际上接近相等。
  2. 尝试通过制作更多桶来减小铲斗。
  3. 按范围正确划分存储桶的想法是,当您搜索某个键时,您将转到相应的范围存储桶和该键中的键,或者它不在整个集合中。所以Concurnetly读取另一个桶是没有意义的。
  4. 我从来没有这样做过,因为我不确定并发是否适用于I \ O,但是从上到下读取整个文件可能会有所帮助,另一个从下到上直到他们见面为止。 (或类似的东西)
  5. 当你将整个桶读入内存时,将其拆分为3-4个arraylists,运行3-4个工作线程来搜索每个阵列上的密钥,搜索必须以更快的速度结束。