hash用于比较java中的对象

时间:2014-01-20 08:34:33

标签: java hash

我需要比较java中的两个对象,如果它们的属性具有相同的值,则应对其进行测试。而不是简单地比较我正在考虑使用哈希函数的所有属性。因此我写了以下代码

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; 
import java.util.Vector;

public class Test {

private static Vector<String> vecA, vecB;

public static void main(String args[]) {
    vecA = new Vector<String>();
    vecB = new Vector<String>();

    vecA.add("hallo");
    vecA.add("blödes Beispiel");
    vecA.add("Einer geht noch");
    vecB.add("hallo");
    vecB.add("blödes Beispiel");
    vecB.add("Einer geht noch");

    System.out.println("HashCode() VecA: " + vecA.hashCode());
    System.out.println("HashCode() VecB: " + vecB.hashCode());

    System.out.println("md5 VecA: " + md5(vecA));
    System.out.println("md5 VecB: " + md5(vecB));

    vecA.add("ungleich");

    System.out.println("HashCode() VecA: " + vecA.hashCode());
    System.out.println("HashCode() VecB: " + vecB.hashCode());

    System.out.println("md5 VecA: " + md5(vecA));
    System.out.println("md5 VecB: " + md5(vecB));

}

private static String md5(Vector<String> v){
    try {
        MessageDigest algorithm = MessageDigest.getInstance("MD5");
        algorithm.reset();
        algorithm.update(vecA.toString().getBytes());
        byte messageDigest[] = algorithm.digest();

        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < messageDigest.length; i++) {
            String hex = Integer.toHexString(0xFF & messageDigest[i]);
            if (hex.length() == 1)
                hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    } catch (NoSuchAlgorithmException nsae) {}
    return null;
}
}

md5功能只是被某些网站复制了。这导致以下输出

HashCode() VecA: -356464767
HashCode() VecB: -356464767
md5 VecA: 6805716958249f5b7f177fc95408713e
md5 VecB: 6805716958249f5b7f177fc95408713e
HashCode() VecA: 1477685990
HashCode() VecB: -356464767
md5 VecA: c76297ce297d5308359ca06f26fb97ca
md5 VecB: c76297ce297d5308359ca06f26fb97ca

我很困惑,在vecA中添加一个元素似乎改变了vecB的md5代码,因此它们的哈希值仍然相同。是什么原因,在这种情况下使用java.security.MessageDigest还是简单的hashCode()是他们的优势?散列函数的性能与所有属性的比较如何?

2 个答案:

答案 0 :(得分:2)

在这两种情况下,您都要为vecA构建md5哈希:

algorithm.update(vecA.toString().getBytes());

应该是

algorithm.update(v.toString().getBytes());
  

原因是什么,在这种情况下使用java.security.MessageDigest或简单地使用hashCode()是他们的优势吗?

不使用hashCode的一个好处是,如果不覆盖该方法,由于{{1的默认实现,同一个类和具有相同属性值的两个实例仍会返回不同的哈希值}}

  

哈希函数的性能与所有属性的比较如何?

如果你只是比较属性一次,可能没有任何明显的性能差异(但是,这取决于你如何比较属性)但是在重复比较多个属性与一次重复计算哈希的情况下比较哈希,后者可能会更快。

修改

这是一个澄清第一句话答案的例子。 请考虑以下简单的代码:

hashCode

正如您所看到的,static class A { int x; public A( int i) { x = i; } } static class B { int x; public B( int i) { x = i; } public int hashCode() { final int prime = 31; return prime * x; } public boolean equals( Object obj ) { //by contract you should always override equals and hashCode together //also note that some checks are omitted for simplicity's sake (obj might be null etc.) return getClass().equals( obj.getClass()) && x == ((B)obj).x; } } A的情况下不会覆盖hashCode。因此,您将获得以下结果:

B

请注意,x在两种情况下都相同,但对于System.out.println(new A( 500 ).hashCode() == new A(500).hashCode()); //false System.out.println(new B( 500 ).hashCode() == new B(500).hashCode()); //true ,使用对象标识,而不是x的值,A#hashCode()

答案 1 :(得分:1)

您的md5方法存在问题

algorithm.update(vecA.toString().getBytes());

可能应该是

algorithm.update(v.toString().getBytes());