我需要在 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
不会覆盖 hashCode
而 B
会覆盖。因此,您将得到以下结果:
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/