经常看到Hash这个东西,比如emule,每次下载完一个文件,它都要对这个文件hash半天,让我们来看看在java里面使用hash类容器的方法。 每个被放入Hash类容器里面的Object(容器里面是不能放int之类的简单数据结构的,必须放入Object)都会通过自己的hashCode()函数产生一个hashCode值,这个东西可以是你自己定义的,通过重载hashCode()函数(建议是,equals(),compareTo()函数也一起重载掉),用来提供一个特定的hash值,这样any object can be used as a key and it will hash by default。 注意,你提供的每个key必须是独一无二的(天下无双^_^),然而hash出来的hashCode不一定是不重复的。比如我们用了一个散列函数是n % m,如果m比较小,那么对于不同的n来说就有可能得到同样的hashcode,至于如何找到一个好的散列函数……问数学系的同学,或者参考《Effective Java》 Java 的首席架构师 Joshua Bloch写的。如果两个hashcode重复了,hash类容器会把有相同hashcode的Object挂在同一个hashcode节点下,用list保存起来,这样如果下次我们查找到这个hashcode节点,就再在这个list里面去查找,这就叫做碰撞(collision),所以如果散列函数设计得不好,碰撞(collision)就会很多,但是吖,鱼和熊掌不可得兼,如果要让碰撞少,就会导致空间浪费严重。还是以数组为例子,你开一个很大的数组才能保证下标取到很大的时候不会取不到,可是中间就有很多用不到的元素了。(这就是桶的作用,桶越多,桶里面就越有可能放到少的元素,参见数学书中关于抽屉原理的说明^_^) 当然你不重载也可以,java中的元类型,就是那个继承体系的祖先Object里面已经提供了hashCode(),至于功能如何……参看下面的文字 This becomes a nuisance if you use the default hashCode() method in objects that you’re using as keys. In this case, an object stored in a hash map can never be retrieved using a different key object instance, even though that key object may be identical in all other respects. Yet this is precisely what you’ll want to do in many cases. 学会一个好词panacea,哈哈哈。发现什么Oxford Cambridge Collins电子词典比起来,Macmillan的速度很快,词也很丰富。不过很奇怪,查不到Spain,而可以查到Spanish……我又说废话了 考虑一个地址薄之类的对象,可以使用诸如名字,地址之类不大可能重复的数据成员来做key,这样查找的时候就可以用名字,地址来查找。 依照上面的讨论,下面来解释一下为什么要在重载hashCode()的时候把equals()函数也一起重载掉。如果是使用对象的数据成员来做key,那么在往容器里面插入的时候要比较是否有重复的key(前面说过,天下无双,嘿嘿),e |
|