在大规模数据上删除java中的重复项

时间:2016-11-21 10:14:53

标签: java

我有以下问题。 我正在使用和API连接到某个地方并将数据作为输入流。 目标是在删除重复行后保存数据。 由第10,15,22列定义的重复。

我使用多个线程获取数据。 目前我首先将数据保存到csv文件中,然后删除重复项。 我想在读数据时这样做。 数据量约为1000万条记录。 我的内存有限,我可以使用。 这台机器有32GB的内存,但我有限,因为有其他应用程序使用它。

我在这里阅读有关使用哈希映射的内容。 但我不确定我有足够的记忆力来使用它。

有没有人建议如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

Hashmap将至少消耗与原始数据一样多的内存。因此,对于数据集的大小可能不太可行(但是,您应该检查它,因为如果是,它是最简单的选项)。

我要做的是将数据写入文件或数据库,计算要进行重复数据删除的字段的哈希值,并使用对文件的适当引用将哈希值存储在内存中(例如,字节索引的位置)原始值在书面文件中)。参考当然应该尽可能小。

当你点击一个哈希匹配时,查找原始值并检查它是否相同(因为不同值的哈希可能会一起出现)。

现在的问题是你期望的重复数量。如果您期望很少匹配,我会选择便宜的写入和昂贵的读取解决方案,即将所有内容线性地转储到平面文件中并从该文件中读回。

如果你期望很多匹配,它可能反过来,即拥有一个索引文件或一组文件,甚至一个数据库(确保它是一个数据库,其中写操作不是太昂贵)。

答案 1 :(得分:1)

解决方案取决于第10,15,22列中您的数据有多大。

假设它不是太大(例如,大约1kb),你实际上可以实现内存解决方案。

  • 实施Key类以存储第10,15,22列中的值。小心实施equalshashCode方法。 (您也可以使用普通ArrayList。)
  • 创建一个Set,其中包含您阅读的所有记录的键。
  • 对于您阅读的每条记录,请检查该密钥是否已存在于该集合中。如果是,请跳过记录。如果没有,请将记录写入输出,将密钥添加到集合中。确保以线程安全的方式使用set。

在最糟糕的情况下,您需要number of records * size of key个内存量。对于10000000条记录和假定的<1kb /密钥,这应该可以使用大约10GB。

如果密钥大小仍然太大,您可能需要一个数据库来存储密钥集。

另一种选择是存储键的哈希而不是完整的键。这将需要更少的内存,但您可能会遇到哈希冲突。这可能导致“误报”,即实际上不重复的错误重复。要完全避免这种情况,您需要一个数据库。

答案 2 :(得分:0)

您可以使用ConcurrentHashSet。它将自动删除重复元素,并且它的线程安全达到一定的限制