在大文件中查找重复项

时间:2012-02-09 17:34:46

标签: algorithm data-structures

我的文件很大,大约有1500万个条目。 文件中的每一行都包含一个字符串(称之为键)。

我需要使用java在文件中找到重复的条目。 我尝试使用散列图并检测重复的条目。 显然这种方法给我一个“java.lang.OutOfMemoryError:Java堆空间”错误。

我该如何解决这个问题?

我想我可以增加堆空间并尝试它,但我想知道是否有更好的有效解决方案而不必调整堆空间。

7 个答案:

答案 0 :(得分:29)

关键是你的数据不适合内存。您可以使用external merge sort

将文件分区为适合内存的多个较小块。对每个块进行排序,消除重复(现在是相邻的元素)。

合并块并在合并时再次消除重复项。由于你将在这里进行n-nway合并,你可以保留内存中每个块的下一个k元素,一旦块的项目耗尽(它们已经合并)从磁盘中获取更多。

答案 1 :(得分:11)

我不确定你是否考虑在java之外做这个,但如果是这样的话,这在shell中非常简单:

cat file | sort | uniq

答案 2 :(得分:6)

您可能无法一次加载整个文件,但您可以将哈希和行号存储在HashSet中没问题。

伪代码......

for line in file
    entries.put(line.hashCode, line-number)
for entry in entries
    if entry.lineNumbers > 1
         fetch each line by line number and compare

答案 3 :(得分:4)

我认为您不需要对数据进行排序以消除重复数据。只需使用快速启发方法。

  1. 从数据中选择k个枢轴(除非您的数据真的很古怪,这应该非常简单)
  2. 使用这些k个轴将数据分成k + 1个小文件
  3. 如果这些块中的任何一块太大而无法容纳在内存中,请重复该块的处理
  4. 一旦你有可管理的大小的块,只需应用你最喜欢的方法(散列?)来找到重复的
  5. 请注意,k可以等于1.

答案 4 :(得分:3)

我可以想象解决这个问题的一种方法是首先使用external sorting algorithm对文件进行排序(搜索external sort java会产生大量带代码的结果)。然后你可以逐行迭代文件,重复现在显然会直接相互跟随,所以你只需要在迭代时记住前一行。

答案 5 :(得分:2)

如果由于内存不足而无法构建完整列表,则可以尝试在循环中执行此操作。即创建一个hashmap但只存储一小部分项目(例如,那些以A开头的项目)。然后你收集重复项,然后继续'B'等。

当然,您可以选择任何类型的“分组”(即前3个字符,前6个等)。

只需要(多次)迭代。

答案 6 :(得分:1)

如果您愿意接受一定数量的统计错误,可以尝试Bloom filter。番石榴provides一个,但现在有一个相当大的错误,可能会在下周发布11.0.2版本。