Java中的"大字典"实现

tso*_*tsi 6 java performance dictionary

我正处于Java项目的中间,该项目将使用单词的"大字典"."字典"是指分配给字符串的某些数字(int).而'big'我的意思是一个100 MB的文件.我提出的第一个解决方案可能是最简单的.在初始化时,我读入整个文件并创建一个大的HashMap,稍后将用于查找字符串.

有没有一种有效的方法可以在初始化时无需读取整个文件?也许不是,但如果文件真的很大,那么按照可用RAM的顺序呢?所以基本上我正在寻找一种在存储在内存中的大型字典中有效查找内容的方法.

感谢到目前为止的答案,结果我意识到我可以在我的问题中更具体.您可能已经猜到应用程序与文本挖掘有关,特别是以稀疏向量的形式表示文本(尽管有些人有其他创造性的想法:)).因此,对于使用至关重要的是能够在字典中查找字符串,尽可能快地获取其密钥.只要字符串查找时间得到优化,"读取"字典文件或将其索引到数据库中的初始开销就不那么重要了.再说一次,我们假设字典大小很大,与可用RAM的大小相当.

lev*_*tov 4

考虑非复制模式ChronicleMaphttps://github.com/OpenHFT/Chronicle-Map )。它是一个堆外 JavaMap实现,或者从另一个角度来看,它是一个超轻量级的 NoSQL 键值存储。

\n\n

它对您开箱即用的任务有何用处:

\n\n
    \n
  • 通过内存映射文件持久化到磁盘(参见 Micha\xc5\x82 Kosmulski 的评论)
  • \n
  • 延迟加载(仅按需加载磁盘页面)->快速启动
  • \n
  • 如果您的数据量大于可用内存,操作系统将自动取消映射很少使用的页面。
  • \n
  • 多个 JVM 可以使用相同的映射,因为堆外内存在操作系统级别上共享。如果您在类似于 Map-Reduce 的框架(例如 Hadoop)中进行处理,则非常有用。
  • \n
  • 字符串以 UTF-8 形式存储,如果字符串大部分是 ASCII,则节省约 50% 的内存(如 maaartinus 指出的)
  • \n
  • int或者long值只需要 4(8) 个字节,就像您有原始专用的映射实现一样。
  • \n
  • 每个条目的内存开销非常小,比标准HashMapConcurrentHashMap
  • \n
  • 如果您已经需要或将来打算并行化文本处理,则可以通过锁条带实现良好的可配置并发性。
  • \n
\n

  • @PeterLawrey我相信,如果你正确地组织特里树,你将永远不会错过超过一页的内容:靠近根部的部分将保留在内存中,并且你不需要超过一页的尾部。恕我直言,当内存紧张时,trie 可能会很有用;trie 仍然可以容纳,而 `HashMap` 则不行(因为它大了 3-10 倍?只是猜测)。然后您会很乐意用一次页面未命中来换取一些缓存未命中。 (2认同)