【问题标题】:removing duplicates in java on large scale data在大规模数据上删除java中的重复项
【发布时间】:2016-11-21 10:14:53
【问题描述】:

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

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

我在这里阅读了有关使用哈希映射的信息。 但我不确定我是否有足够的内存来使用它。

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

【问题讨论】:

  • 您有 API 给出的输出示例吗?是由三列 (10,15,22) 的组合定义的重复,还是这些列中的每一列都必须是唯一的而不参考其他列?
  • api 的输出是一个类似这样的字符串:="banna",="orange",="apple"... 等大约 30 个元素。这些列的组合是关键。

标签: java


【解决方案1】:

Hashmap 至少会占用与原始数据一样多的内存。因此,对于您的数据集的大小,这可能是不可行的(但是,您应该检查一下,因为如果是,这是最简单的选择)。

我要做的是将数据写入文件或数据库,计算要删除的字段的哈希值,并将哈希值存储在内存中,并提供对文件的适当引用(例如,位置的字节索引)原始值在写入的文件中)。引用当然应该越小越好。

当您遇到哈希匹配时,查找原始值并检查它是否相同(因为不同值的哈希可能会落在一起)。

现在的问题是您期望有多少重复项。如果您期望很少有匹配项,我会选择一种廉价的写入和昂贵的读取解决方案,即将所有内容线性转储到一个平面文件中并从该文件中读取。

如果您期望有很多匹配项,则可能相反,即拥有一个索引文件或一组文件,甚至是一个数据库(确保它是一个写入操作不太昂贵的数据库)。

【讨论】:

  • 如果我对密钥进行哈希处理并将其插入列表(或链接列表)并检查列表是否存在哈希,如果不存在,我将直接写入目标文件,如果存在,我将忽视?我除了拥有大约 200 万条唯一记录。
  • 正如@lexicore 提到的,您可能有哈希冲突,即两个不同的值可能具有相同的哈希。如果您可以为您的用例提供一个特殊的哈希函数来保证避免哈希冲突,那么您可以按照您的描述进行操作。否则,一旦找到相同的哈希值,就必须比较实际的基础值。一个例外是可以接受省略一些唯一条目的用例(一个相当不寻常的场景)。
【解决方案2】:

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

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

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

在最坏的情况下,您需要number of records * size of key 的内存量。对于 10000000 条记录,假设每个密钥

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

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

【讨论】:

    【解决方案3】:

    您可以使用 ConcurrentHashSet。它会自动删除重复的元素,并且在一定限度内它是线程安全的

    【讨论】:

    • 内存限制是多少?它会处理我拥有的数据量吗?
    猜你喜欢
    • 2018-10-25
    • 2019-02-23
    • 2014-04-23
    • 2011-08-08
    • 1970-01-01
    • 2021-05-16
    • 2015-11-07
    • 1970-01-01
    • 2011-04-09
    相关资源
    最近更新 更多