Java 计算大型文本文件的词频

Java 计算大型文本文件的词频,java,algorithm,data-structures,text-files,word-count,Java,Algorithm,Data Structures,Text Files,Word Count,我有一个巨大的文本文件(大于可用的RAM内存)。我需要计算所有单词的频率,并将单词和频率计数输出到一个新文件中。结果应按频率计数的降序排序 我的做法: 对给定文件进行排序-外部排序 按顺序计算每个单词的频率,将计数存储在另一个文件中(与单词一起) 根据频率计数-外部排序对输出文件进行排序 我想知道是否有更好的方法来做这件事。我听说过基于磁盘的哈希表吗?或者B+树,但以前从未尝试过 注意:我看到过类似的问题,但没有一个需要解决数据大于内存的问题 编辑:根据这些评论,大家一致认为词典实际上应该放在今

我有一个巨大的文本文件(大于可用的RAM内存)。我需要计算所有单词的频率,并将单词和频率计数输出到一个新文件中。结果应按频率计数的降序排序

我的做法:

  • 对给定文件进行排序-外部排序
  • 按顺序计算每个单词的频率,将计数存储在另一个文件中(与单词一起)
  • 根据频率计数-外部排序对输出文件进行排序
  • 我想知道是否有更好的方法来做这件事。我听说过基于磁盘的哈希表吗?或者B+树,但以前从未尝试过

    注意:我看到过类似的问题,但没有一个需要解决数据大于内存的问题


    编辑:根据这些评论,大家一致认为词典实际上应该放在今天计算机的内存中。但是,让我们假设一个单词词典,它太大了,无法放入内存。

    如果唯一单词的列表和频率适合内存(而不是文件,只是唯一的单词),您可以使用哈希表按顺序读取文件(无需存储)


    然后,您可以根据出现的次数对哈希表的条目进行排序。

    我将采用
    map reduce
    方法:

  • 在节点上分发文本文件,假设节点中的每个文本都可以放入RAM
  • 计算节点中每个单词的频率。(使用哈希表)
  • 在主节点中收集每个结果并将它们全部合并

  • 所有独特的单词可能都适合记忆,所以我会使用这种方法:

    • 创建字典(
      HashMap
    • 逐行阅读这个巨大的文本文件
    • 将新词添加到字典中,并将值设置为1
    • 将现有单词的值加1
    解析整个大型文件后:

    • 按频率对字典排序
    • 将已排序的字典中的单词和频率写入新文件

    请注意将单词转换为小写或大写。

    最好的方法是逐行读取文件,并将单词存储到多重映射中(例如)。如果此映射扩展了您的内存,您可以尝试使用键值存储(例如Berkeley JE DB或)。这些键值存储的工作方式类似于地图,但它们将其值存储在硬盘上。我使用MapDB解决了一个类似的问题,速度非常快。

    您使用的是哪种编程语言?所有不同的单词都比RAM大?如果您只想计算单词数,可以逐行或按文件流读取文件。您不需要将整个文件加载到RAM中。文件中有多少不同的单词?如果你不存储副本,它们会被存储在内存中吗?真的吗?多少公羊?即使是一本完整的词典也可以放入今天的计算机RAM中……因为海报声称,即使是文件中使用的单词词典也不能放入他的微型RAM中(???)我对这个解决方案投+1票-当只有一台机器按顺序进行切片时,这种方法也有效。我按顺序考虑了这种方法,但是如何有效地组合结果呢?对每个结果文件进行单独排序,然后全部打开并逐行读取,决定是否添加结果(相同的单词)和/或根据字母表中的顺序,将哪个单词/nr对写入结果文件。是的,这几乎就是外部排序的作用。除了我们不需要对整个文件进行排序之外,仅仅对切片进行排序就足够了。但是你能把字典里的每个词都分类吗?这会导致更快地搜索未来的单词吗?不会。。。在添加所有单词后对词典进行排序。为什么选择
    词典
    ?该类被标记为过时。@Matteo:我不建议使用
    字典
    类。除了过时之外,它也是一个抽象类,没有任何用处。单词
    字典
    的选择基于
    HashMap
    的用途。假设大多数单词不重复。在读取文件大小为1字节(PiB)的内容时,这种方法可以正常工作吗?很酷,我会尝试一下。