java - 用于在 Java 中比较对象的哈希

标签 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() 的原因是什么?它们有什么优势吗?哈希函数的性能与所有属性的比较相比如何?

最佳答案

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

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

应该是

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

Whats the reason and is their any advantage in using java.security.MessageDigest or simply hashCode() in that case?

不使用 hashCode 的一个优点是,如果该方法未被重写,同一类和具有相同属性值的两个实例仍会返回不同的哈希值,因为默认实现哈希码

How about the performance of hash functions vs. comparisons of all attributes?

如果您只比较一次属性,可能不会有任何明显的性能差异(然而,这取决于您比较属性的方式)但是如果重复比较多个属性与一次又一次地计算哈希值比较哈希,后者可能更快。

编辑:

这里有一个例子来阐明第一条引述的答案。 考虑以下简单的代码:

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 不会覆盖 hashCodeB 会覆盖。因此,您将得到以下结果:

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() 使用的是对象标识,而不是像 B#hashCode() 那样使用 x 的值>

关于java - 用于在 Java 中比较对象的哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21229336/

相关文章:

java - 如何解决这个java方法中的stackoverflow异常?

java - 在 servlet 容器启动后立即调用对 localhost 的请求

java - 如何在二叉树中搜索一个节点并返回它?

java - 如何在对话框可见时更改对话框的模式

java - 每次生成不同的密码哈希

file - 判断两个 MP3 文件是否重复的最快方法是什么?

python - 返回用 dict 构造的散列而不是仅使用花括号语法有什么好处吗?

java - 约束验证顺序 - Jersey

ruby - 使用 HashMap 测试顺序

perl - 使用表示哈希结构的字符串访问哈希引用数据