将大文件标记为Java中的哈希表

时间:2011-11-04 21:23:43

标签: java hashmap corpus

我遇到了这个问题:我正在阅读900个文件,在处理完文件后,我的最终输出将是HashMap<String, <HashMap<String, Double>>。第一个字符串是fileName,第二个字符串是word,double是字频。处理顺序如下:

  • 读取第一个文件
    • 阅读文件的第一行
    • 将重要标记拆分为字符串数组
    • 将字符串数组复制到我的最终地图,增加字频率
  • 重复所有文件

我正在使用字符串BufferedReader。问题是,在处理完第一个文件之后,Hash变得如此之大,以至于一段时间后性能非常低。我想听听这方面的解决方案。我的想法是在限制达到存储到文件后创建一个有限的哈希。这样做直到处理完所有内容,最后混合所有哈希值。

5 个答案:

答案 0 :(得分:1)

为什么不一次只读一个文件,并将该文件的结果转储到磁盘,然后读取下一个文件等?显然,每个文件在映射方面都独立于其他文件,那么为什么要在编写第二个文件时保留第一个文件的结果呢?

您可以将每个文件的结果写入另一个文件(例如foo.txt =&gt; foo.txt.map),或者您可以在结果之间创建一个带有某种分隔符的单个文件,例如

==== foo.txt ====
word - 1
the - 3
get - 3
==== bar.txt ====
apple - 2
// etc

顺便问一下,为什么你使用double作为频率?当然它应该是一个整数值......

答案 1 :(得分:1)

哈希映射处理的时间不应随着增长而显着增加。由于散列函数不合适或填充太多,您的地图可能会出现偏差。除非你使用的内存比你从系统中获得的内存多,否则你不必分手。

当我在内存中运行包含大量对象的大型哈希映射(或任何集合)时,我所看到的是VM试图运行垃圾收集器时疯狂。它达到了这样的程度,即90%的时间用于JVM开始垃圾收集器,这需要一段时间,并且发现几乎每个对象都有一个引用。

我建议分析你的应用程序,如果它是垃圾收集器,那么增加堆空间并调整垃圾收集器。此外,如果您可以近似所需的哈希映射大小并提供足够大的分配(请参阅构造函数中的initialCapacity和loadFactor选项),它将会有所帮助。

答案 2 :(得分:0)

您可以尝试使用此库来提高性能。

http://high-scale-lib.sourceforge.net/

它类似于java集合api,但是性能很高。如果您可以在小批量处理这些结果后批量处理并合并这些结果,那将是理想的选择。

这篇文章将帮助您提供更多输入。

http://www.javaspecialists.eu/archive/Issue193.html

答案 3 :(得分:0)

我想重新考虑你的问题:

因为您正在尝试构建倒排索引:

  1. 使用Multimap而不是Map<String, Map<String, Integer>>

    Multimap<word, frequency, fileName, .some thing else tomorrow>

  2. 现在,读取一个文件,构建Multimap并将其保存在磁盘上。 (类似于Jon的回答)

  3. 阅读x文件后,将所有Multimaps合并在一起:putAll(multimap)如果您确实需要一个包含所有值的公共地图。

答案 4 :(得分:0)

为什么不使用自定义类

public class CustomData {
 private String word;
 private double frequency;
 //Setters and Getters
}

并将您的地图用作

Map<fileName, List<CustomData>>

这样至少你的地图上只有900个键。

-Ivar