- 浏览: 848391 次
- 性别:
- 来自: 草帽海贼团
文章分类
最新评论
-
大维啊:
估计只有你自己能明白
Java安全沙箱机制 -
moonljt521:
第五种方式,如果构造里想传入参数怎么做,例如android的 ...
单例模式的七种写法 -
javaDADY:
怎么感觉在讨论茴香豆的茴字有几种写法?
单例模式的七种写法 -
Wallen_Han:
Mr.Cheney 写道这样的:Mr.Cheney 写道还有一 ...
单例模式的七种写法 -
Wallen_Han:
60love5 写道第三种稍微有点Java基础就知道是错的,被 ...
单例模式的七种写法
首先说建议的情况: 比如你的对象想放到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简单的实现,我们来看看你就明白了:
- //: containers/SimpleHashMap.java
- // A demonstration hashed Map.
- import java.util.*;
- import net.mindview.util.*;
- public class SimpleHashMap<K,V> extends AbstractMap<K,V> {
- // Choose a prime number for the hash table
- // size, to achieve a uniform distribution:
- static final int SIZE = 997;
- // You can't have a physical array of generics,
- // but you can upcast to one:
- @SuppressWarnings("unchecked")
- LinkedList<MapEntry<K,V>>[] buckets =
- new LinkedList[SIZE];//List数组里每项是个List,数组下标是hashcode方法的返回值再经过散列函数得到的,相当于散列表的关键字,它亦代表着每个对象的关键字。(不能显示new一个泛型数组,但是你可以new一个泛型数组的引用,如有需要以后可以将普通数组转型为泛型数组)。
- public V put(K key, V value) {//将这个对键值放进hashmap中。
- V oldValue = null;
- int index = Math.abs(key.hashCode()) % SIZE;//这里就是通过散列函数对hashcode的返回值处理得到一个关键字,它代表了对象在数组里的位置,既是数组下标。
- if(buckets[index] == null)
- buckets[index] = new LinkedList<MapEntry<K,V>>();//如果是第一次散列到这个数组下标,那么就新生成一个LinkedList,可以看到它里面保存的是MapEntry<K,V>键和值。
- LinkedList<MapEntry<K,V>> bucket = buckets[index];//将这个LinkedList赋值给一个bucket(桶),以后就直接在这个bucket进行操作。
- 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)) {//如果已经存在同一个键值,那么就更新value。
- oldValue = iPair.getValue();
- it.set(pair); // Replace old with new
- found = true;
- break;
- }
- }
- if(!found)
- buckets[index].add(pair);//如果是一个新的键值,那么直接添加到这个LinkedList中。
- return oldValue;
- }
- public V get(Object key) {//看hashmap是如何凭借hashcode方法快速定位到键值。
- int index = Math.abs(key.hashCode()) % SIZE;[color=red]//与put方法中的作用一样,生成数组下标,因为我存的时候就是存到这个地方的,那么我取的时候直接访问buckets[index]。[/color]
- if(buckets[index] == null) return null;//直接访问这个数组下标的LinkedList,如果为null,则返回。
- for(MapEntry<K,V> iPair : buckets[index])//为什么要用LinkedList,因为hashcode方法产生的散列码不能完全确定一个对象,也就是说会和其他对象发生“碰撞”,即散列到同一个数组下标,解决这个问题的组号办法就是定义一个List把它们保存起来,但是在这个List中,我们必须保证能用equals方法确定对象的身份,这也就是为什么很多人说hashcode()相等,equals()不一定相等,而equals()相等的两个对象,hashcode()一定相等。所以这里要直接在LinkedList执行线性查找。
- 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());
- }
- } /* Output:
- {CAMEROON=Yaounde, CONGO=Brazzaville, CHAD=N'djamena, COTE D'IVOIR (IVORY COAST)=Yamoussoukro, CENTRAL AFRICAN REPUBLIC=Bangui, GUINEA=Conakry, BOTSWANA=Gaberone, BISSAU=Bissau, EGYPT=Cairo, ANGOLA=Luanda, BURKINA FASO=Ouagadougou, ERITREA=Asmara, THE GAMBIA=Banjul, KENYA=Nairobi, GABON=Libreville, CAPE VERDE=Praia, ALGERIA=Algiers, COMOROS=Moroni, EQUATORIAL GUINEA=Malabo, BURUNDI=Bujumbura, BENIN=Porto-Novo, BULGARIA=Sofia, GHANA=Accra, DJIBOUTI=Dijibouti, ETHIOPIA=Addis Ababa}
- Asmara
- [CAMEROON=Yaounde, CONGO=Brazzaville, CHAD=N'djamena, COTE D'IVOIR (IVORY COAST)=Yamoussoukro, CENTRAL AFRICAN REPUBLIC=Bangui, GUINEA=Conakry, BOTSWANA=Gaberone, BISSAU=Bissau, EGYPT=Cairo, ANGOLA=Luanda, BURKINA FASO=Ouagadougou, ERITREA=Asmara, THE GAMBIA=Banjul, KENYA=Nairobi, GABON=Libreville, CAPE VERDE=Praia, ALGERIA=Algiers, COMOROS=Moroni, EQUATORIAL GUINEA=Malabo, BURUNDI=Bujumbura, BENIN=Porto-Novo, BULGARIA=Sofia, GHANA=Accra, DJIBOUTI=Dijibouti, ETHIOPIA=Addis Ababa]
怎样?现在应该知道hashcode方法的作用了吧,它就是用来提高效率的,有句话说得好:为速度而散列。因为散列的Set和Map是基于hashcode方法来查找对象的,所以你在使用这些类的时候一定要覆盖hashcode方法,而非散列的Set和Map,例如TreeSet,TreeMap等,它们只需equals方法就可以唯一确定对象的身份。这样说,想必已经很清楚了吧。
评论
3 楼
C_J
2009-11-07
貌似我看JDK源码的时候大概的意思是
public boolean equals(Object obj){
return this.hashCode()==obj.hashCode()?true:false;
}
以上是伪代码,想表达的意思是 equals是用hashCode来比较的...
public boolean equals(Object obj){
return this.hashCode()==obj.hashCode()?true:false;
}
以上是伪代码,想表达的意思是 equals是用hashCode来比较的...
2 楼
yidao620c
2009-08-21
嗯。讲的很不错。
1 楼
superhack
2009-08-20
一直没明白, 这下好了 ! 讲得很清楚 !
发表评论
-
解决eclipse每次启动maven很慢
2012-11-14 12:31 17871好久没有用eclipse了,离开人人后maven私有仓库当然也 ... -
Debug控
2011-08-02 14:34 3611我是一个debug控,很 ... -
泛型のwhy&how
2011-07-21 18:35 1421Why,Java为什么需要 ... -
【分享】Findbugs反模式
2011-05-20 09:54 5274FindBugs解释 FindBugs 是一个静态分 ... -
Findbugs反模式
2011-05-20 09:46 0FindBugs介绍 FindBugs 是一个静态分 ... -
正则表达式Mini版
2010-10-27 12:14 13851.句点符号:. 条件 ... -
Eclipse下jar包版本不一致等常见问题
2010-09-15 20:18 8002我借这个平台简单说说Eclipse下配置环境需要注意的几点 ... -
我承认我没有if(xxx != null)
2010-09-08 12:08 3049昨天正在编码兴头时 ... -
jtextfield限制字数与数字输入
2010-02-21 15:40 64import javax.swing.text.*; p ... -
Swing线程机制以及invokeLater和invokeAndWait
2009-09-14 11:05 7133本人最近想写一个仿QQ,初学Swing对线程机制不太了解,所以 ... -
第五惑:初始化和动态绑定之间的小小冲突
2009-04-04 23:46 1258今天骑车去都江堰了,很累很累,没准备好今天该发什么Tips,所 ... -
第四惑:属性是否被动态绑定?
2009-04-03 17:11 1180众所周知,方法可以被动态绑定,在子类被向上转型为父类时,虚拟机 ... -
第三惑:类型被动使用举例
2009-04-02 13:04 1434当类型属于被动使用的 ... -
第二惑:类型在没有被完全初始化之前就生成实例对象所表现的情况
2009-04-01 13:41 1501public class MainTest { publi ... -
第一惑:类初始化时,final修饰的静态字段的表现方式
2009-03-31 16:27 1851计划从今天开始,模仿一下jythoner大哥,不过不是Java ... -
Java动态绑定虚拟机实现
2009-03-25 20:19 1734今天在51CTO看到一篇很好的介绍Java动态绑定的文章。先转 ... -
Java虚拟机简单介绍
2009-03-25 20:17 110请参考:http://cantellow.iteye.com/ ... -
Java夜未眠·经典句子选载
2009-03-25 20:16 2868最近在读前辈蔡学镛《Java夜未眠·程序员的心声》,几天就看完 ... -
代码签名和认证
2009-03-25 20:06 1781要对一段代码作担保或 ... -
Java安全沙箱机制
2009-03-25 20:05 4648说明,本文部分内容转 ...
相关推荐
重写 `hashCode()` 方法时,我们需要确保当两个对象满足 `equals()` 的条件时,它们的哈希码也相同。同时,为了提高性能,我们应该尽量让不同的对象产生不同的哈希码。例如,对于上述Person类,可以这样重写 `...
Java重写equals同时需要重写hashCode的代码说明,以及如何重写hashCode方法,此代码演示按照effective java书籍说明的重写思路。代码中演示了使用集合存储对象,并且对象作为key,需重写equals和hashCode.
第二种情况:对于采用哈希算法的集合,集合中对象必须重写 hashCode 方法,同时也要重写 equals 方法。这是因为哈希算法需要使用 hashCode 方法来计算对象的哈希值,而 equals 方法用于判断两个对象是否相等。 如何...
例如,在Hashtable、HashMap、HashSet、LinkedHashMap等容器中,我们需要重写hashcode()方法,使其生成对象的哈希码,以便于快速地查找和比较对象。 compareTo()方法是Comparable接口中的一个方法,它用于比较两个...
为什么重写equals方法,还必须要重写hashcode方法
在Java编程语言中,`equals()` 和 `hashCode()` 方法是对象的基本组成部分,它们在很多场景下都发挥着至关重要的作用。这两个方法与对象的相等性比较和哈希表(如HashMap、HashSet)的运作紧密相关。这篇博客将深入...
在Java编程语言中,`equals()` 和 `hashCode()` 方法是两个非常重要的成员,尤其是在处理对象比较和集合操作时。这两个方法通常与`Object`类中的默认实现相关联,但为了在实际开发中实现正确的对象比较和哈希表操作...
因此,为了保证对象在集合中的正确行为,当重写 `equals` 方法时,必须同时重写 `hashCode` 方法,确保相等的对象具有相同的哈希值。这样,集合可以正确地识别和处理相等的对象,避免数据一致性问题。同时,遵循这个...
#### 二、为什么需要重写equals方法? 1. **提高程序效率**:当两个对象具有相同的业务逻辑上的“身份”时,它们应该被认为是相等的。 2. **增强代码可读性**:重写后的`equals`方法可以根据实际需求来判断对象是否...
在Java编程中,`equals()` 和 `hashCode()` 方法是Object类中的两个重要方法,它们在处理对象相等性以及在哈希表(如HashSet、HashMap)中起到关键作用。当自定义类时,有时需要根据业务逻辑重写这两个方法以满足...
在Java编程语言中,`equals()` 和 `hashCode()` 方法是对象的基本组成部分,它们与对象的比较和哈希表(如 `HashMap`)的操作密切相关。在面试中,面试官提出的问题直指这两个方法的重要关联。 首先,`equals()` ...
然而,在实际应用中,我们往往需要根据对象的内容来判断它们是否相等,因此在自定义类中重写 `equals()` 方法是常见的做法。例如,`String` 类就重写了 `equals()`,比较两个字符串的字符序列是否相同。 接着,我们...
在这个示例代码中,我们重写了 equals() 方法和 hashCode() 方法,以便比较两个 Name 对象的值是否相等,并生成对象的哈希码。 结论 在 Java 中,重写 equals() 方法和 hashCode() 方法是非常重要的,它们可以确保...
当我们在自定义类中重写 `equals()` 方法时,通常也需要重写 `hashCode()` 方法,这是为了遵循一些重要的原则和保证数据结构如 `HashMap`、`HashSet` 的正确行为。 首先,`equals()` 方法用于比较两个对象是否相等...
为了使对象能够基于其内容(即属性值)来判断相等性,我们需要重写 `Equals` 方法。 **重写示例:** 假设我们有一个名为 `Person` 的类,其中包含 `Name` 和 `Age` 属性。为了根据这两个属性的值来判断两个 `...
equals 与 hashCode 方法讲解 equals 方法和 hashCode 方法是 Java 语言中两个重要的方法,它们都是在 Object 类中定义的...在实际开发中,我们需要根据具体情况来重写这两个方法,以确保对象的正确比较和哈希码计算。
"Java重写equals及hashcode方法流程解析" Java中的equals和hashCode方法是两个非常重要的方法,它们都是Object...同时,我们还需要注意到,重写equals方法时,必须重写hashCode方法,以便于确保对象的正确性和一致性。
在Java编程语言中,`equals()`, `hashCode()` 和 `toString()` 是三个非常重要的方法,它们主要用于对象的比较、哈希存储以及打印对象信息。这三个方法是Java对象的基础特性,对于理解和开发高质量的Java程序至关...
【面试】中提到的几个关键知识点集中在对象比较、equals()和hashCode()方法的使用以及它们之间的关系上。这些概念在Java编程中至关重要,特别是在处理集合类和比较对象时。 1、**hashCode与equals两者之间的关系**...
重写`equals()`和`hashCode()`的目的是确保在使用如HashSet这样的集合时,如果两个对象被视为相等(即`equals()`返回`true`),那么它们的`hashCode()`也应该相同。这是因为HashSet依赖于`hashCode()`来确定对象在...