';大词典';Java实现 我在一个java项目的中间,它将使用一个单词的大词典。“字典”指的是分配给字符串的某些数字(int)。我所说的“大”是指100MB的文件。我提出的第一个解决方案可能是最简单的。在初始化时,我读入整个文件并创建一个大的HashMap,稍后将用于查找字符串

';大词典';Java实现 我在一个java项目的中间,它将使用一个单词的大词典。“字典”指的是分配给字符串的某些数字(int)。我所说的“大”是指100MB的文件。我提出的第一个解决方案可能是最简单的。在初始化时,我读入整个文件并创建一个大的HashMap,稍后将用于查找字符串,java,performance,dictionary,Java,Performance,Dictionary,有没有一种在初始化时不需要读取整个文件的有效方法?也许不是,但是如果文件真的很大,比如说按照可用RAM的顺序,该怎么办?所以基本上,我在寻找一种方法,在存储在内存中的大型词典中高效地查找内容 谢谢你迄今为止的回答,因此我意识到我的问题可以更具体一些。正如您可能猜到的,该应用程序与文本挖掘有关,特别是以稀疏向量的形式表示文本(尽管有些人有其他创造性的想法:)。因此,使用的关键是能够在字典中查找字符串,尽快获取它们的密钥。只要字符串查找时间得到优化,“读取”字典文件或将其索引到数据库中的初始开销就没

有没有一种在初始化时不需要读取整个文件的有效方法?也许不是,但是如果文件真的很大,比如说按照可用RAM的顺序,该怎么办?所以基本上,我在寻找一种方法,在存储在内存中的大型词典中高效地查找内容


谢谢你迄今为止的回答,因此我意识到我的问题可以更具体一些。正如您可能猜到的,该应用程序与文本挖掘有关,特别是以稀疏向量的形式表示文本(尽管有些人有其他创造性的想法:)。因此,使用的关键是能够在字典中查找字符串,尽快获取它们的密钥。只要字符串查找时间得到优化,“读取”字典文件或将其索引到数据库中的初始开销就没有那么重要。再次,让我们假设字典的大小很大,与可用RAM的大小相当

当您的数据结构与RAM的数量相差几百MB时,最好不要在运行时初始化数据结构,而是使用支持的数据库(目前大多数数据库都支持)。一旦文件变得如此之大,并且运行在JVM的-设置上,索引将是确保最快检索文本的唯一方法之一。这是因为,如果您的文件与最大大小设置一样大,或者比最大大小设置大得多,那么您将不可避免地要删除它

至于必须在初始化时读取整个文件。您最终必须这样做,以便能够高效地搜索和分析代码中的文本。如果您知道一次只搜索文件的某一部分,则可以实现。如果不是这样,您不妨咬紧牙关,将整个文件加载到数据库中。如果代码执行的其他部分不依赖于此,则可以在此过程中实现

如果您有任何问题,请告诉我

如评论中所述,a将为您节省大量内存

你也应该考虑使用<代码>字节<代码> s,而不是< Case> char < /C> > s,因为这可以为纯ASCII文本节省2的因子,或者在使用国家字符集时,只要不超过256个不同的字母即可。 乍一看,将这种低级优化与尝试相结合毫无意义,因为它们的节点大小由指针控制。但是如果你想去低水平的话,还是有办法的

因此,使用的关键是能够在字典中查找字符串,尽快获取它们的密钥

然后忘记任何数据库,因为它们与
HashMap
s相比非常慢

如果它不适合内存,最便宜的解决方案通常是获取更多。否则,考虑只加载最常见的单词,并为其他人做一些比较慢的操作(例如,内存映射文件)。
我被要求指出一个好的实现,特别是堆外实现。我不知道有什么

假设OP不需要易变性,特别是键的易变性,这一切看起来都很简单

我想,整本字典可以很容易地打包成一个
ByteBuffer
。假设大部分是ASCII码,并且有一些位攻击,则箭头每个箭头标签字符需要1个字节,子指针需要1-5个字节。子指针将是相对的(即当前节点和子节点之间的差异),这将使它们中的大多数在存储在一个字节中时可以放入一个字节


我只能猜测总的内存消耗量,但我会说,它听起来太大,无法存储在内存中。要么将其存储在关系数据库中(简单,在散列上有索引,fast),要么存储在NoSQL解决方案中,如Solr(小学习曲线,非常快)


虽然NoSQL很快,但是如果你真的想要调整性能,并且有比其他人更频繁查找的条目,考虑使用有限大小的缓存来保存最近使用的(10000)查找。

在非复制模式下考虑<代码> ScReimLAMP < /代码>()。它是一个堆外Java

Map
实现,或者从另一个角度看,它是一个超轻量的NoSQL键值存储

它对您的开箱即用任务有用的功能:

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

您可以读取特定字节大小的文件,将其存储在
HashMap
对象中,然后将此对象作为ByTestStream对象存储在硬盘上。重复此步骤,直到您阅读完整个文件。@Mohammad,这并不真实