Java存储并比较磁盘

时间:2016-07-06 06:21:00

标签: java key-value key-value-store

我有一个场景,我必须比较2个地图。我必须获取源Map的键并遍历目标Map以获得equals的键,然后比较它们的值。问题是这些地图应该保持非常高(> = 10,000,000)的记录量。所以我不能将这些地图保存在内存中。

可能的解决方案:

将两者作为文本文件存储为“key = value”

问题:

我们必须为源中的每个键值迭代目标Map文本文件,这是无效且耗时的。

可能的解决方案: 将两者作为文本文件存储为“key = value”并创建id =>目标行号的索引

问题:

没有有效的方法可以根据大文本文件中的行号直接读取行。有些方法使用api用于Java 1.8,他们再次需要将文件加载到内存中

可能的解决方案:

将两者存储在数据库中

问题:

在这种情况下,我们必须查询每个键值的数据库。如果我们在源和目标中有100万个密钥,我们必须查询100万次。无效且耗时

可能的解决方案:

使用mapDB

问题:

尝试了这一点,但在260,000条记录后失败了。它给了一个Writer线程失败的异常,主要是因为我使用的是32位JVM。所以我想自己编写实现而不是依赖MapDB。

如何有效地存储/检索和比较键值映射,以便在进行比较时不会达到很高的性能。在任何时候我都无法将任何内容带入内存中,因为它会给出Out of Memory异常。解决方案应该读取和写入磁盘,而不是内存 - 我没有12 GB的RAM。该解决方案也适用于32/64位系统

2 个答案:

答案 0 :(得分:4)

一个相当简单的选择:

  • 将地图放在磁盘上
  • 对它们进行排序(以多种方式中的任何一种)
  • 为每张地图打开一个阅读器,并阅读第一行
  • 迭代每张地图的线条,根据"当前"的比较,决定要从哪个地图读取?密钥。

这样,你在任何时候都只需要内存中的两个键/值对。

例如,假设我们有一个"来源"用键A,B,H,I和a"目标"映射;用键B,C,I,J映射。过程看起来像这样:

  • 阅读来源= A,目标= B
  • 比较:目标之前的源,因此从源(B)
  • 读取另一行
  • 比较:源键和目标键是相等的,因此处理B的条目,并从每个键中读取另一行(source = H,target = C)
  • 比较:源头之前的目标,因此从目标(I)
  • 读取另一行
  • 比较:目标之前的源,所以从源(I)
  • 读取另一行
  • 比较:源键和目标键是相等的,因此处理I的条目,并从每个键中读取另一行(source = empty,target = J)
  • 由于我们已经耗尽了来自数据源的数据,我们已经完成了

答案 1 :(得分:0)

感谢@Jon的算法。这是我对问题的实施。如果有任何错误或者可以改进,请告诉我。

<Licence>
    <NUMBER>123124124</NUMBER>
    <SERIAL>JKP231234</SERIAL>
</Licence>
<Licence>
    <NUMBER>123124124</NUMBER>
    <SERIAL>JKP231234</SERIAL>
</Licence>
<Licence>
    <NUMBER>123124124</NUMBER>
    <SERIAL>JKP231234</SERIAL>
</Licence>
<Licence>
    <NUMBER>123124124</NUMBER>
    <SERIAL>JKP231234</SERIAL>
</Licence>

<Signature>AFSDGARTYSDFH346347DFHQYADFHDSZJWSDFBSART</Signature>