为什么80%的码农都做不了架构师?>>>   

首先说建议的情况:  比如你的对象想放到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一个泛型数组的引用,如有需要以后可以将普通数组转型为泛型数组)。[/color]public V put(K key, V value) {// 将这个对键值放进hashmap中。[/color]V oldValue = null;int index = Math.abs(key.hashCode()) % SIZE;// 这里就是通过散列函数对hashcode的返回值处理得到一个关键字,它代表了对象在数组里的位置,既是数组下标。[/color]if (buckets[index] == null)buckets[index] = new LinkedList<MapEntry<K, V>>();// 如果是第一次散列到这个数组下标,那么就新生成一个LinkedList,可以看到它里面保存的是MapEntry<K,V>键和值。[/color]LinkedList<MapEntry<K, V>> bucket = buckets[index];// 将这个LinkedList赋值给一个bucket(桶),以后就直接在这个bucket进行操作。[/color]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。[/color]oldValue = iPair.getValue();it.set(pair); // Replace old with newfound = true;break;}}if (!found)buckets[index].add(pair);// 如果是一个新的键值,那么直接添加到这个LinkedList中。[/color]return oldValue;}public V get(Object key) {// 看hashmap是如何凭借hashcode方法快速定位到键值。[/color]int index = Math.abs(key.hashCode()) % SIZE;// 与put方法中的作用一样,生成数组下标,因为我存的时候就是存到这个地方的,那么我取的时候直接访问buckets[index]。[/color]if (buckets[index] == null)return null;// 直接访问这个数组下标的LinkedList,如果为null,则返回。[/color]for (MapEntry<K, V> iPair : buckets[index])// 为什么要用LinkedList,因为hashcode方法产生的散列码不能完全确定一个对象,也就是说会和其他对象发生“碰撞”,即散列到同一个数组下标,解决这个问题的组号办法就是定义一个List把它们保存起来,但是在这个List中,我们必须保证能用equals方法确定对象的身份,这也就是为什么很多人说hashcode()相等,equals()不一定相等,而equals()相等的两个对象,hashcode()一定相等。所以这里要直接在LinkedList执行线性查找。[/color]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方法就可以唯一确定对象的身份。这样说,想必已经很清楚了吧

转载于:https://my.oschina.net/leoson/blog/286452

为什么要重写hashCode()相关推荐

  1. JAVA中重写equals()方法的同时要重写hashcode()方法

    object对象中的 public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true:注意:当此方法 ...

  2. 重写 equals 方法就一定要重写 hashCode 方法?其实有个前提

    作者 l 会点代码的大叔(CodeDaShu) 如果问到 == 和 equals 的区别,相信很多程序员同学都能脱口而出:一个是判断地址,一个是判断内容. 但是如果继续追问:"你重写过 eq ...

  3. 为什么使用HashMap需要重写hashcode和equals方法_java常见面试题敲黑板了,HashMap最全的整理,大厂必考...

    最近几天,在这样的大环境下显得疲惫不堪,但是我还是写下了这篇文章,希望对任何人都有用. HashMap是我们经常用到的数据结构,由数组和链表组成的数据结构如下图所示 上方是一张数组图片,数组里面每个地 ...

  4. 为什么使用HashMap需要重写hashcode和equals方法_为什么要重写 hashcode 和 equals 方法?...

    1. 通过Hash算法来了解HashMap对象的高效性 2. 为什么要重写equals和hashCode方法 3. 对面试问题的说明 <Java 2019 超神之路> <Dubbo ...

  5. HashMap存自定义对象为什么要重写 hashcode 和 equals 方法?

    HashMap的k放过自定义对象么? 当我们把自定义对象存入HashMap中时,如果不重写hashcode和equals这两个方法,会得不到预期的结果. class Key{private Integ ...

  6. hashcode相等的两个对象一定相等吗_为什么重写 equals方法时一定要重写hashCode方法?...

    推荐阅读: 一线架构师总结SpringBoot,Cloud,Nginx与Docker,不信你搞不懂 47天洒热血复习,我终于"挤进"了字节跳动(附面经+学习笔记) 五年时间,从蘑菇 ...

  7. java 为什么重写equals一定要重写hashcode?

    前言 最近复习,又看到了这个问题,在此记录和整理,通过例子来说明这种情况的原因,使大家可以清晰明白这个问题. 初步探索 首先我们要了解equals方法是什么,hashcode方法是什么. equals ...

  8. 为什么要重写hashcode( )和equals( )?

    打个比方,一个名叫张三的人去住酒店,在前台登记完名字就去了99层100号房间,此时警察来前台找叫张三的这个人住在哪间房,经过查询,该酒店住宿的有50个叫张三的,需要遍历查询,查询起来很不方便. 那么就 ...

  9. 为什么重写equals一定要重写hashCode方法?

    大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白. 下面我们看下Objec ...

  10. 为什么要重写hashcode()方法

    主要原因是默认从Object继承来的hashCode是基于对象的ID实现的. 如果你重写了equals,比如说是基于对象的内容实现的,而保留hashCode的实现不变,那么很可能某两个对象明明是&qu ...

最新文章

  1. php table转json,html table表数据转Json格式示例代码分析
  2. Python把PDF文件中每页内容分离为独立图片文件
  3. codevs 4927 线段树练习5 线段树基本操作模板
  4. go 输入输出流(fmt)
  5. 火狐浏览器插件(XPI 文件)签名指南
  6. 【等价变换】—— 指数对数函数
  7. 工业大数据发展面临四方面挑战
  8. ansible 第一次练习
  9. 【深入JVM内核—原理、诊断与优化】第2期开课了
  10. 实时 摔倒识别 /运动分析/打架等异常行为识别/控制手势识别等所有行为识别全家桶 原理 + 代码 + 数据+ 模型 开源!
  11. 【编程知识】常用参考表对照表
  12. c语言编程开发app,C语言编程app
  13. html5 在线设计,推荐十款非常优秀的 HTML5 在线设计工具
  14. 照片文件与计算机系统,照片文件格式怎么修改
  15. 普元 AppServer 部署时页面提示部署失败,后台报错:Unable to load class org.apache.cxf.ws.policy.AssertionBuilder
  16. CSS3渐变属性:线性渐变和径向渐变用法教程
  17. OriginPro常用配置
  18. 西门子S7-1200和人机界面测试
  19. UDT 最新协议分析
  20. signature=f380c172efecdd0f7b9329d16d09ca45,Virtual Identity Signs in Online Communication

热门文章

  1. C++_一维数组案例_五只小猪称体重_案例元素逆置(调换)_案例冒泡排序---C++语言工作笔记020
  2. k8s核心技术-Pod(健康检查)_健康检查的方式_以及pod崩溃后如何处理---K8S_Google工作笔记0023
  3. security工作笔记008---springBoot springCloud中的security配置全解
  4. delphi Hi 和 High
  5. 终端中用命令成功修改linux~Ubuntu PATH环境变量
  6. 随想录(windows上cuda环境安装)
  7. 头像裁剪框html css,CSS3 clip-path实现的用户头像裁剪效果
  8. hci0 没反应_哄女朋友专用表情包~你说你没女朋友?先收藏着嘛,万一有了呢?...
  9. java计算器问题反馈,Java开发网 - 求教计算器问题(急~~~)
  10. 主板有电无法启动_主板通电但不能启动怎么回事