HashSet of Strings占用了太多内存,建议……?

我目前正在HashSet中存储一个单词列表(大约120,000个),目的是用作列表来检查被激活的单词,看它们是否拼写正确,只返回是或否。

我想知道是否有办法做到这一点,占用更少的内存。 目前120,000个单词约为12meg,单词读取的实际文件大约为900kb。

有什么建议么?

提前致谢

查看布隆filter或布谷鸟哈希。 布隆filter还是布谷鸟哈希?

我不确定这是否是您的问题的答案,但值得研究这些替代方案。 bloomfilter主要用于拼写检查器类用例。

您可以使用前缀树或trie: http : //en.wikipedia.org/wiki/Trie

HashSet可能不是正确的结构。 请改用Trie 。

这可能有点晚了但是使用谷歌你可以很容易地找到我刚刚发布的DAWG调查和C代码。

http://www.pathcom.com/~vadco/dawg.html

TWL06 – 178,691字 – 适合494,676字节

压缩共享节点结构的缺点是它不能作为列表中单词的哈希函数。 也就是说,它会告诉您一个单词是否存在,但它不会返回一个确实存在的单词的相关数据的索引。

如果您想要完美和完整的哈希function,那么在处理器缓存大小的结构中,您将不得不阅读,理解和修改名为ADTDAWG的数据结构。 它将比传统的DAWG略大,但它更快,更有用。

http://www.pathcom.com/~vadco/adtdawg.html

一切都是最好的,

JohnPaul Adamovsky

12MB存储120,000个字每个字约100个字节。 可能至少32个字节是字符串开销。 如果单词平均为10个字母并且它们存储为2字节字符,则会占另外20个字节。 然后是对HashSet中每个String的引用,这可能是另外4个字节。 剩下的44个字节可能是HashSet条目和索引开销,或者我上面没有考虑过的。

最简单的事情是String对象本身的开销,它可以占用比存储实际字符数据所需的更多的内存。 因此,您的主要方法是开发一个自定义表示,避免为每个字符串存储单独的对象。 在执行此操作的过程中,您还可以摆脱HashSet开销,因为您真正需要的只是一个简单的单词查找,这可以通过直接二进制搜索来完成,该数组将成为您的自定义实现的一部分。

您可以将自定义实现创建为int类型的数组,每个单词都有一个元素。 这些int元素中的每一个都将被分成子字段,这些子字段包含长度和指向char类型的单独支持数组的偏移量。 将这两者放入管理它们的类中,并支持公共方法,允许您在给定字符串索引和可选字符索引的情况下检索和/或转换数据和单个字符,并在单词列表上执行简单搜索这是您的拼写检查function所需要的。

如果您的基础字符串数据不超过16777216个字符(例如,120,000个字符串乘以10个字符的平均长度= 120万个字符),则可以采用每个int的低24位并存储每个字符串的起始偏移量进入char数据的后备数组,并取每个int的高位8位并存储相应字符串的大小。

你的char数据将把你以前的字符串拼凑在一起而没有任何分隔符,完全依赖于int数组来知道每个字符串的开始和结束位置。

采用上述方法,您的120,000个单词(平均每个10个字母)将需要大约2,400,000个字节的后备arrays数据和480,000个字节的整数索引数据(120,000 x 4个字节),总计2,880,000个字节,这是关于比上面报告的目前12MB金额节省75%。

数组中的单词将按字母顺序排序,您的查找过程可以是int数组上的简单二进制搜索(从每个测试的char数组中检索相应的单词),这应该是非常有效的。

如果您的单词恰好是完全ASCII数据,则可以通过将后备数据存储为字节而不是字符来节省额外的1,200,000个字节。

如果您需要更改这些字符串,这可能会变得更加困难。 显然,在你的情况下(拼写检查),你不需要(除非你想支持用户添加到列表中,无论如何这都是偶然的,因此重写char数据和索引以添加或删除单词可能是可以接受的)。

节省内存以节省内存的一种方法是使用基数树 。 这比trie好,因为前缀不是冗余存储的。

当你的字典被修复时,另一种方法是为它构建一个完美的哈希函数。 您的哈希集不需要桶(以及相关的开销),因为不会发生冲突。 使用开放寻址的哈希表/哈希集的每个实现都可以用于此(如谷歌集合的ImmutableSet )。

问题在于设计:出于拼写检查原因在HashSet中存储如此大量的单词并不是一个好主意:

您可以使用拼写检查程序(例如: http: //softcorporation.com/products/spellcheck/),也可以使用前缀树(描述: http://en.wikipedia)构建“auto-wordcompletion” 。 org / wiki / Trie )。

在此设计中无法减少内存使用量。

您还可以尝试Radix Tree ( Wiki , Implementation )。这有些像trie但更有效的内存。