Java 对字符串进行内存和速度高效的搜索

Java 对字符串进行内存和速度高效的搜索,java,algorithm,data-structures,size,space-efficiency,Java,Algorithm,Data Structures,Size,Space Efficiency,我有一堆字符串我想快速查找。每个字符串的长度为22个字符,仅由前12个字符(也就是“键”)查找,整个字符串集将定期重新创建。它们从文件中加载,并在文件更改时刷新。我必须处理太少的可用内存,我的VPS上的其他服务器进程也需要它,而且需要更多 如何最好地存储字符串并搜索它们 我目前的想法是将它们一个接一个地存储在char[]中(以节省RAM),并对它们进行排序,以便更快地查找(我认为如果我对它们进行了预排序,则查找速度最快,以便使用或搜索)。但我不确定我应该如何编写它-如果有人想玩一个具有挑战性的拼

我有一堆
字符串
我想快速查找。每个字符串的长度为22个字符,仅由前12个字符(也就是“键”)查找,整个字符串集将定期重新创建。它们从文件中加载,并在文件更改时刷新。我必须处理太少的可用内存,我的VPS上的其他服务器进程也需要它,而且需要更多

如何最好地存储字符串并搜索它们

我目前的想法是将它们一个接一个地存储在
char[]
中(以节省RAM),并对它们进行排序,以便更快地查找(我认为如果我对它们进行了预排序,则查找速度最快,以便使用或搜索)。但我不确定我应该如何编写它-如果有人想玩一个具有挑战性的拼图游戏:这里是

顺便说一句:在重新创建/排序过程中,暂时超出内存限制是可以的,但不应该太长或太长

谢谢

更新

对于“我想知道细节”的人群(如果我在Java细节中有错误,请纠正我):源文件包含大约32万个条目(全部是ANSI文本),我真的希望(一直!)保持在64 MB RAM使用率以下,数据只是我程序的一部分。这里有一些关于内存的信息

我的VPS是32位操作系统,所以

  • 一个
    字节[]
    ,所有串联=12+长度字节
  • 一个
    char[]
    ,所有连接=12+长度*2字节
  • String
    =32+长度*2字节(是对象,具有
    char[]
    +3
    int
所以我必须记住:

  • 如果全部存储在
    字节[]中,则约7 MB
  • 如果全部存储在
    char[]
  • 如果全部存储在
    字符串[]中,则约25 MB
  • >40 MB,如果它们存储在哈希表/映射中(为此,我可能需要微调初始容量)

哈希表并不神奇——它有助于插入,但原则上它只是一个非常长的字符串数组,其中哈希代码模容量用作索引,数据存储在索引后的下一个空闲位置,如果在查找时找不到,则按线性搜索。但对于哈希表,我需要字符串本身和前12个字符的子字符串进行查找。我不想这样(或者我错过了什么吗?),对不起,伙计们…

我可能会使用缓存解决方案,甚至番石榴也可以。当然,先对它们进行排序,然后进行二进制搜索。不幸的是我没有时间:(

听起来a将是适合这种情况的正确实现

搜索在固定时间内完成,刷新可以在线性时间内完成


(警告PDF)

我自己编写了一个解决方案,但它与我发布的问题略有不同,因为我可以使用我没有发布的信息(对不起,下次我会做得更好)

我回答这个问题是因为问题已经解决了,我不会接受其他答案中的一个,因为它们并没有真正帮助克服记忆限制(而且对我的口味来说有点短)。他们仍然每人都有一张选票,没有任何不愉快的感觉,谢谢你花时间

我设法将所有信息分为两个长字符串(密钥完全位于第一个长字符串中)。前12个字符是一个ISIN,可以压缩为长字符,因为它只使用数字和大写字母,总是以两个大写字母开头,以一个可以从其他字符重构的数字结尾。所有可能值的乘积留下略多于3位的余位

我将源文件中的所有条目存储在
long[]
中(第一个是压缩的ISIN,第二个是其他内容),并根据两个long中的第一个对它们进行排序

当我通过一个键进行查询时,我将其转换为long,进行二进制搜索(我可能会将其更改为插值搜索)并返回匹配的索引。值的不同部分可以通过所述索引进行检索-我从数组中获取第二个long,解包并返回请求的数据


结果是:RAM使用量从~110MB下降到<50MB,包括Jetty(顺便说一句,我以前使用过哈希表),查找速度非常快。

如果你每次只问一个问题,会有所帮助仅基于您所面临的一个狭隘问题,例如:内存使用、排序算法、数据结构。哈希表有什么问题吗?还有,您的性能是否有任何限制?我没有性能限制,但它仍然不应该花费太长时间。哈希表对我来说不起作用(请参阅上面的更新)@AaronKurtzhals:我不认为这会有帮助,因为决策会相互影响。但我希望有关我约束的附加信息会有所帮助。你对哈希表的厌恶很难理解。事实上,它们是O(1)对于插入和查找,除非哈希代码退化。这可能是最佳选择,但使用两个
long[]
将更容易,因为可以使用现有的排序和二进制搜索(每次查找的代价是三级缓存未命中)。不,不会。两个long必须相邻(因此,我使用
索引
索引+1
获取所有数据)。如果我将其拆分为两个数组,并使用现有的
排序
二进制搜索
,它们将被独立排序,关联将丢失。您是对的。关于排序,您需要一个临时的
HashMap
来创建第二个
长[]
,这将临时占用大量内存。或者您拥有并行处理两个数组的排序,但这正是我想要避免的。