使用hashcode来比较java中的两个大字符串?

时间:2011-10-06 13:17:49

标签: java arrays file hash

我有两个文件正在读取,我在两个文件中都找到了一些行。我需要编写一个函数来检测两个文件中找到哪些行。现在我为此编写了代码,它将读取文件1的内容并将记录放入arraylist,然后读取文件2,对于file2中的每一行,我检查它是否在arraylist中找到,如果找到,我知道它是一个重复的行。现在我的问题是我在arraylist中保存完整的行,我想知道是否有可能将我读取的行转换为哈希码,然后我将这个哈希码保存到arraylist中,之后,我将比较这个哈希码到我从file2读取的行的哈希码,这是更好的节省内存的方法吗?

6 个答案:

答案 0 :(得分:5)

如果两个哈希码不同,则行不同。如果两个哈希码相同,则这些行可能相同也可能不同。

如果您将文件存储在HashSet中,则查看行是否已存在是一种非常快速的操作。 HashSet在内部使用哈希码。

答案 1 :(得分:3)

这种方法可以节省内存,但不能保证匹配。哈希码的定义表明它们不是唯一的。如果要存储较小版本的字符串,则应存储字符串的摘要,如MD5。

以下是你如何获得摘要。

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
...
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digestBytes = md.digest(string.getBytes());

MD5长度为16个字节,因此如果字符串长度超过8个字符(每个字符2个字节),这只会节省内存。

但除非你的文件非常大,否则你真的不需要担心内存,HashSet答案会给你更好的结果。

修改

MD5确实会发生冲突,但不会在现实世界中发生冲突。它不应该用作加密哈希码,但在这种情况下可以正常工作。还有其他的摘要功能,如SHA256,它们碰撞的可能性较小,但它们的摘要大小较大。

答案 2 :(得分:2)

您正在寻找HashSet<String> - 它将完全符合您的需求!


示例:

Set<String> file1       = ....// read line by line from file1
ArrayList<String> file2 = ... //     -     "      -     file2

for (String line : file1)
    if (file2.contains(line))
        duplicate found

答案 3 :(得分:0)

如果您真的担心记忆并愿意为了安全记忆而表现较差,您可以执行以下操作:

  1. 为文件1创建哈希值的HashSet。
  2. 从文件2创建一个哈希值,该哈希值与文件1中的哈希值匹配。
  3. 从文件1创建一个HashSet,其哈希值在HashSet 2中。
  4. 根据HashSet 3检查文件2中的每一行。

答案 4 :(得分:0)

你没有提到文件的大小限制,所以我假设它们可能足够大,无法将所有行存储在内存中。

所以,我建议采用以下方法:

  1. 连接两个文件以创建一个大文件。

  2. 使用“外部”排序算法,例如http://code.google.com/p/externalsortinginjava/对大文件进行排序。

  3. 读取已排序的文件,一次一行,并将每一行与之前的行进行比较(仅在内存中保留两行 - 当前行和上一行)。如果当前行和前一行相同,则该行将出现在两个原始文件中。

  4. 在计算的早期阶段经常需要“外部排序”,因为可用的内存要少得多。一种方法是/是Merge Sort,当与磁带一起使用时(记得磁带?),称为“磁带排序”。是的,我老了:-)

答案 5 :(得分:0)

如果您担心空间/内存问题,请将字符串转换为base36,然后再按照多人的建议将其存储在HashSet中。为了标准化,我建议从字符串中剥离所有空格和标点符号,并在创建base36等效项之前将其转换为小写。然后在HashSet中,您最终得到HashSet<String>,其中String包含字符串的base36编码而不是整个字符串。