【问题标题】:Need to search a big file of integers using Java需要使用 Java 搜索一个大整数文件
【发布时间】:2017-03-11 21:02:34
【问题描述】:

我有一个包含 100,000 行的文件,每行是一个由空格分隔的 1000 个整数(范围从 0 到 1,000,000)的列表。现在我需要创建一个 API,当给定两个输入 a 和 b 时,它会告诉我文件的同一行中是否存在两个数字,其中 b 在索引方面位于 a 之后。文件总大小约为 700 MB。

由于它是一个 API,我不能每次都通过创建流从文件中读取,因为我必须注意响应时间并且磁盘读取速度很慢。由于文件太大,我无法将所有内容加载到内存中。

关于什么是最佳方式的任何建议?

注意 - 我通过将所有内容加载到内存并制作数字哈希图来创建 API -> 它所属的行集,然后尝试搜索它。它适用于较小的文件,但是当我尝试用较大的文件启动服务器时,服务器无法启动(我也是 JAVA 的新手,谁能帮我看看在哪里查看它为什么没有启动的日志?。我我只是在我的 bash 脚本中执行 java -jar $DIR/target/test.jar)

【问题讨论】:

  • 700 MB 太大了?
  • 服务器不启动时报什么错误?如果它是内存不足的消息,您可能只需为其分配更多内存来解决问题,除非您预见这些文件会变得更大(比如超过几 GB)。
  • 我假设上限是一百万。不均匀的逗号分组是印度独有的怪癖,我正在编辑以反映标准用法。
  • 此外,具有 2 个 Integer 对象作为键和值的 HashMap 对于内存使用来说并不是非常理想的。您可能想研究使用使用标准整数而不是对象的本机 Java 集合:labs.carrotsearch.com/hppc.html,但这是一个高级主题。
  • @john16384 如果程序化方法很小、不雅且处理不当,即使 7 MB 也相当大

标签: java file search memory


【解决方案1】:

我认为这里有很多数字(100M),如果您想将它们全部保存在内存中,您应该准备使用 Gbs 的 ram。好消息是最高数字是 1M,因此会产生很多数字重复。

我可能会用图表来表示文件。每个节点都包含一个数字(1-1000000),因此您有 100 万个节点,为 O(1) 访问快速索引(节点可以很容易地实现为数组的单元格)。如果 Y 出现在文件的任何一行中 X 的右侧,则每个节点 X 都连接到节点 Y。

解决方案涉及找到图中两个节点的连通性。我不是这里的专家,我会实现类似 dfs 的算法,注意避免循环。由于这种避免,查找算法将触及最多 100 万个节点,从而降低复杂度。

关于空间:每行应该产生 999 个连接,即(乘以 100k 行)= 几乎 1 亿个连接。如果每个连接是 4 个字节(但您可以改进,因为您只需要 20 位来存储 100 万个),那么您有 400Mb 的内存用于连接。

因此,使用 400Mb 的 ram,您可以让您的 API 响应速度非常快。

【讨论】:

  • 首先感谢您的宝贵意见。我也会这样做,但问题是数据驻留在文件中。要创建图表本身,您将需要大量时间。如果您在内存中的某处预加载图形(可能是 redis 或一些图形数据库,如 neo4js),则只能考虑优化此解决方案。但是由于我必须从文件中读取它(这是约束),所以这个解决方案可能不起作用。事实上,如果允许预加载,我可以创建一个散列,其中键是数字之一(1-1000000),值是包含该数字所在的所有行的集合。
  • 等等 - 你说你尝试预加载没有成功,并不是说它是不允许的。如果允许,您应该这样做:无论初始化需要多少时间(还要考虑将构建后的图形结构保存为输入文件的替换,以便更快地预加载)。您提出的解决方案(number->#lines 的哈希图)具有更高的内存消耗,这可能导致您在原始帖子中所述的预加载失败。
  • 只是对您尝试过的解决方案的评论:对数字 1-1M 使用 HashMap 并不是最佳的,因为具有基于索引的数组(因此空间为 n 并且访问真正为 1)。设置为值也是如此,因为您将其用作列表。除此之外,即使您使用数组而不是 map/set(并优化空间),您仍然需要在索引查找后读取文件;这仍然是低效的。
  • 杰克,如果我已经在内存中有映射,我不需要在索引查找后读取文件。创建图形并保存该结构也将占用相同数量的内存(节点和边)。如果我错了,请纠正我。
  • 抱歉,是你设置了严格的限制“不能每次都从文件中读取”和“不能在内存中加载所有内容”。让我们进行连贯的辩论。如果您没有内存限制,理想的情况是使用 1Mx1M 位图(15Gb 内存)。如果你有限制而不是连贯地处理它们。不想读取文件?使用图表。你有足够大的内存但不是很大?拿着一张地图-(中间空间,非常快)。可以将文件保存在内存中还是可以读取它?行索引很好。是最优的吗?可能不会。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多