Java 我们如何引用文件的特定行?
我在读关于算法问题的书,其中一个是: 有一个包含数百万行数据的文件,有两行 都是一样的。这些行太长了,可能无法放入内存。发现 两条相同的线 建议的解决方案是读取部分行,并为每行创建哈希。Java 我们如何引用文件的特定行?,java,algorithm,file,data-structures,hash,Java,Algorithm,File,Data Structures,Hash,我在读关于算法问题的书,其中一个是: 有一个包含数百万行数据的文件,有两行 都是一样的。这些行太长了,可能无法放入内存。发现 两条相同的线 建议的解决方案是读取部分行,并为每行创建哈希。 例如,通过构建第1行的第1部分(可在内存中读取)的散列,然后构建第1行的第2部分到第1行的第N部分的散列,来构建第1行的散列。 将哈希存储在文件或哈希表中。对于任何相同的哈希值,请比较行。如果线是一样的,我们就解决了 虽然我对这个解决方案有很高的理解,但我不知道如何实现它。如何将散列与文件中的特定行关联?这是语
例如,通过构建第1行的第1部分(可在内存中读取)的散列,然后构建第1行的第2部分到第1行的第N部分的散列,来构建第1行的散列。
将哈希存储在文件或哈希表中。对于任何相同的哈希值,请比较行。如果线是一样的,我们就解决了 虽然我对这个解决方案有很高的理解,但我不知道如何实现它。如何将散列与文件中的特定行关联?这是语言实现的细节吗?
例如,在Java中,我们如何解决这个问题?真正的答案是购买更多内存。在Java2GB中可以拥有的最长字符串,它将适合现在的机器。您可以用不到200美元的价格购买32GB
但是为了解决这个问题,我建议你
- 找到每行的偏移量
- 找到长度相同的线(使用偏移差)
- 计算具有相同长度的行的64位或更长哈希值
- 对于具有相同哈希的行,进行逐字节比较
1) 哪个API可以找到偏移量 计算已读取的字节数,这就是偏移量 2) 真正的答案是“购买更多内存”项目经理不同意这一点。你有不同的经历吗 我向他们指出,如果他们认为可以很好地利用资源,我可以花一天的时间节省100美元的可重用内存,这可能会花费他们1000美元以上(即使这不是我得到的报酬)。我让他们决定;)
我8岁的儿子在一台个人电脑上有8GB的内存,因为他的内存花了我24英镑。但是你是对的,有些项目经理认为8GB对于一个每小时花费那么多的专业人员来说太多了!?我有16GB的电脑,我不使用它来运行任何严肃的东西,因为我在256GB的机器上工作。现在,您可以购买容量为2 TB的机器,这对于大多数应用程序来说都是多余的。;) 虽然我同意解决方法是利用现代技术,并利用当今内存的廉价性,但问题在于锻炼大脑,了解如何在给定的约束条件下解决问题 你提到的散列非常简单。 java解决方案可以利用一些隐藏的东西,这些东西可能会掩盖实际发生的事情,因此我将首先解释解决方案,然后解释java实现 通用解决方案: 散列(如SHA1、MD5等)通过压缩输入生成整数。假设您只能在每行中存储前MB的字符
- 您将迭代每一行,获得第一个MB的字符,并将其传递给哈希算法(例如MD5)
- 然后将散列映射为键,将行号列表/数组映射为值李>
- 在第一次传递之后,任何具有匹配的前MB字符的行都将以相同的哈希结束,从而位于映射中的相同列表中
- 要准备第二次通过,请搜索地图并剔除仅包含一个行号的任何列表
- 然后,通过从地图中的其余条目中编译行号来创建行号列表,这些行号将是第二遍中唯一选中的行号
- 第二步,从行列表中的每一行提取第二MB字符,对它们进行散列,并以与第一步相同的方式将它们放入映射中
- 迭代映射中的条目,剔除只有一个行号的散列条目
- 重复第二步,但增加字符块(MB),使其与密码一致
- 当您到达一个过程,其中只有一个具有多个行号的哈希,并且该哈希只有两个元素时,这些行就是相同的两行
HashMap<String,ArrayList<Integer>>
HashMap
对于您的主地图,您只需执行每个调用即可
- map.get(mbBlock).add(行号);当然,您应该检查这是否是第一次使用这个键,这样您就不会得到空指针异常
- 每次通过后,剔除只包含一行的条目
- 在剩下的几行重复,直到只剩下两个行号
算法的诀窍在于将大问题分解为小问题,并充分利用前面步骤的结果。通过映射,可以将散列值映射为一行,这样键就是散列值,值就是行号。只需存储字节偏移量。@Cratylus:常规文件IO(或NIO)API(streams).@Cratylus:不读取文件就无法读取文件。@Cratylus:不需要一次存储整行来计算换行符。1)使用哪个API来查找偏移量?2)
真正的答案是购买更多内存
项目经理并不真正同意这一点