- cantellow
- 等级:
- 性别:
- 文章: 311
- 积分: 110
- 来自: 草帽海贼团
|
首先说建议的情况: 比如你的对象想放到Set集合或者是想作为Map的key时(非散列的Set和Map,例如TreeSet,TreeMap等),那么你必须重写equals()方法,这样才能保证唯一性。当然,在这种情况下,你不想重写hashCode()方法,也没有错。但是,对于良好的编程风格而言,你应该在重写equals()方法的同时,也重写hashCode()方法。
然后再说说必须重写hashCode()的情况: 如果你的对象想放进散列存储的集合中(比如:HashSet,LinkedHashSet)或者想作为散列Map(例如:HashMap,LinkedHashMap等等)的Key时,在重写equals()方法的同时,必须重写hashCode()方法。
这里我想讲讲sun的设计者为什么需要设计hashcode方法,也许这样你就应该知道什么时候该重写它了。 数据结构有一种为了提高查找的效率而存在的数据结构——散列表,散列表其实是普通数组概念的推广,因为可以对数组进行直接寻址,故可以再O(1)时间内访问数组的任意元素,thinking in java中有个对hashmap简单的实现,我们来看看你就明白了:
-
-
- import java.util.*;
- import net.mindview.util.*;
-
- public class SimpleHashMap<K,V> extends AbstractMap<K,V> {
-
-
- static final int SIZE = 997;
-
-
- @SuppressWarnings("unchecked")
- LinkedList<MapEntry<K,V>>[] buckets =
- new LinkedList[SIZE];
- public V put(K key, V value) {
- V oldValue = null;
- int index = Math.abs(key.hashCode()) % SIZE;
- if(buckets[index] == null)
- buckets[index] = new LinkedList<MapEntry<K,V>>();
- LinkedList<MapEntry<K,V>> bucket = buckets[index];
- MapEntry<K,V> pair = new MapEntry<K,V>(key, value);
- boolean found = false;
- ListIterator<MapEntry<K,V>> it = bucket.listIterator();
- while(it.hasNext()) {
- MapEntry<K,V> iPair = it.next();
- if(iPair.getKey().equals(key)) {
- oldValue = iPair.getValue();
- it.set(pair);
- found = true;
- break;
- }
- }
- if(!found)
- buckets[index].add(pair);
- return oldValue;
- }
- public V get(Object key) {
- int index = Math.abs(key.hashCode()) % SIZE;[color=red]
- if(buckets[index] == null) return null;
- for(MapEntry<K,V> iPair : buckets[index])
- if(iPair.getKey().equals(key))
- return iPair.getValue();
- return null;
- }
- public Set<Map.Entry<K,V>> entrySet() {
- Set<Map.Entry<K,V>> set= new HashSet<Map.Entry<K,V>>();
- for(LinkedList<MapEntry<K,V>> bucket : buckets) {
- if(bucket == null) continue;
- for(MapEntry<K,V> mpair : bucket)
- set.add(mpair);
- }
- return set;
- }
- public static void main(String[] args) {
- SimpleHashMap<String,String> m =
- new SimpleHashMap<String,String>();
- m.putAll(Countries.capitals(25));
- System.out.println(m);
- System.out.println(m.get("ERITREA"));
- System.out.println(m.entrySet());
- }
- }
-
-
-
怎样?现在应该知道hashcode方法的作用了吧,它就是用来提高效率的,有句话说得好:为速度而散列。因为散列的Set和Map是基于hashcode方法来查找对象的,所以你在使用这些类的时候一定要覆盖hashcode方法,而非散列的Set和Map,例如TreeSet,TreeMap等,它们只需equals方法就可以唯一确定对象的身份。这样说,想必已经很清楚了吧。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
返回顶楼 |
|
|
- superhack
- 等级: 初级会员
- 性别:
- 文章: 42
- 积分: 40
- 来自: 北京
|
一直没明白, 这下好了 ! 讲得很清楚 !
|
返回顶楼 |
|
|
- yidao620c
- 等级:
- 性别:
- 文章: 225
- 积分: 240
- 来自: 广州
|
嗯。讲的很不错。
|
返回顶楼 |
|
|
- C_J
- 等级:
- 性别:
- 文章: 331
- 积分: 330
- 来自: 北京
|
貌似我看JDK源码的时候大概的意思是
public boolean equals(Object obj){
return this.hashCode()==obj.hashCode()?true:false;
}
以上是伪代码,想表达的意思是 equals是用hashCode来比较的...
|
返回顶楼 |
|
|