通过Java中的键聚合文件中的键值行

mic*_*ia4 6 java memory hashmap key-value guava

我有一个巨大的文件,由~800M行(60g)组成.行可以是重复的,由id和值组成.例如:

id1   valueA
id1   valueB 
id2   valueA 
id3   valueC
id3   valueA
id3   valueC
Run Code Online (Sandbox Code Playgroud)

注意:ids不按示例中的顺序(和分组).

我希望按键聚合行,这样:

id1   valueA,valueB
id2   valueA
id3   valueC,valueA
Run Code Online (Sandbox Code Playgroud)

有5000个可能的值.

该文件不适合内存,因此我无法使用简单的Java集合.此外,行的最大部分是单个(例如id2),它们应该直接写在输出文件中.

出于这个原因,我的第一个解决方案是迭代两次文件:

  • 在第一次迭代中,我存储了两个结构,只有id和没有值:
    • 单值ids(S1)
    • 多个值ids(S2)
  • 在第二次迭代中,在从内存中丢弃单值id(S1)之后,我可以直接将单值id-value对写入输出文件,检查它们是否不在多个值id中(S2)

问题是我无法完成第一次迭代导致内存限制.

我知道可以通过多种方式解决问题(键值存储,映射缩减,外部排序).

我的问题是什么方法可以更适应使用和快速实施?它只是一次进程,我更喜欢使用Java方法(而不是外部排序).

ymz*_*ymz 1

当处理如此大量的数据时,我们需要跳出框框思考 - 并缓冲整个数据

首先:它已经运行得怎么样了?

假设我有 4GB 的视频,我正在尝试将其加载到我的视频播放器中。我的播放器基本上需要执行 2 个主要操作:

缓冲- 将视频“分割”成块并一次读取一个块(缓冲区)

流式传输- 将结果(视频)显示到我的软件(播放器)

为什么?因为不可能一次将所有内容加载到内存中(我们甚至并不真正需要它......在特定时刻,用户从缓冲区中观察到视频的一部分(这是整个文件的一部分)

第二:这对我们有什么帮助?

我们可以对大文件做同样的事情:

  1. 将主文件拆分为更小的文件(每个文件包含 X 行,其中 X 是“缓冲区”)
  2. 将其加载到java并对其进行分组
  3. 将结果保存到新文件中

在此过程之后,我们有许多小文件,其中包含如下信息

id1   valueA,valueB
id2   valueA
id3   valueC,valueA
Run Code Online (Sandbox Code Playgroud)

因此每个分组文件包含的行数少于其派生的原始小文件的行数

  1. 我们现在可以将其合并回来并尝试将其加载到 java 并重新组合所有内容
  2. 如果该过程失败(仍然太大),我们可以将小分组文件合并为几个分组文件(并重复该过程)