我希望通过简单的哈希比较两个Java Map
。
每个对象都在不同的计算机上,因此通过网络发送哈希将比发送整个对象进行比较更便宜。
例如,我有一个ExampleClass的两个HashMap
Map<String,ExampleClass> One=new ...;
Map<String,ExampleClass> Other=new ...;
我不需要确定所有元素都相同, 这足以让我信任哈希。
我正要在每一侧进行迭代并创建一个“自制哈希”,然后将其发送到网络,最后比较int
或其他东西。
如果在每次从Collection中添加或删除对象时计算此“哈希”,那将是很好的,这样可以避免迭代整个对象。我必须封装Map
的每个添加/删除。有没有Java库可以做到这一点?
答案 0 :(得分:6)
如果您的所有课程都实施hashCode()
(不使用"default" memory address hashcode),您可以使用map's hashCode()
。
这里需要注意的是,如果你的ExampleClass
没有实现hashCode()
,那么相同的项可能在两台不同的机器上有不同的哈希值,这将导致地图的不同哈希值。
澄清:
Map
实现hashCode()
,定义为Map.Enytry
的{{1}}的和。
Map.Entry
's hashCode()
被定义为键hashCode()
的 xor 和值hashCode()
。
您的密钥为hashCode()
s - 它们定义良好String
(两个相等的字符串始终具有相同的hashCode()
)。
您的值为hashCode()
个实例 - 他们也需要明确定义的ExampleClass
。
总之,包含hashCode()
的地图的哈希码将等于:
{ s1 -> ec1, s2 -> ec2 }
意味着取决于(s1.hashCode() ^ ec1.hashCode()) + (s2.hashCode() ^ ec2.hashCode())
的{{1}} 。
如果ExampleClass
确实以hashCode()
给出相等ExampleClass
的方式实施hashCode()
,那么一切都会正常运作。
如果ExampleClasse
未实现hashCode()
,则会使用ExampleClass
的{{1}},这几乎总会给您不同的hashCode()
。
答案 1 :(得分:1)
一个简单的解决方案就是对地图中每个对象的散列进行xor或其简单推导。因为a ^ a = 0
和a ^ b ^ a = b
对于所有a和b,(xor是可交换的,关联的,并且它自己的逆),并且因为xor是便宜的,所以你的添加和删除可以只是xor(可能是派生的)哈希已添加或删除项目的代码。
您可能希望使用派生哈希值来避免地图具有所有相同的键和值的情况,但它们之间的某些映射是转置的。一个简单的派生哈希可能是key.hashCode() - value.hashCode()
,这可以避免大多数情况。
因此,您的代码可能如下所示:
public class MyMap<K, V> extends HashMap<K, V>{
private int hash = 0;
@Override
public int hashCode() {return hash;}
@Override
public V put(K key, V value) {
V old = super.put(key, value);
if (old != null) this.hash ^= key.hashCode() - old.hashCode();
this.hash ^= key.hashCode() - value.hashCode();
return ret;
}
@Override
public V remove(K key) {
V ret = super.remove(key);
if (ret != null) this.hash ^= key.hashCode() - ret.hashCode();
return ret;
}
}
请注意,根据实施情况,某些更高级的方法(例如,从集合中添加多个项目)可能安全,也可能不安全。