1.JDK规定,equals相等的两个对象hashCode也必须相等,这两个方法都是从Object上面继承而来的,通过观察JDK源码可以发现Object的equals方法是对2个对象的地址(逻辑地址,也就是在JVM中映射一个物理地址)比较,而hashCode又是一个本地方法,其实hashCode就是内存中的一个地址,换句话说,2个相等的对象(地址相等)那么他们的hashCode也肯定是相等的,反过来hashCode不相等,equals也一定不相等,但是hashCode相等equals却不一定相等,因为在生成hashCode的时候可能有冲突,还有一种情况就是JDK的String、Integer等等这些类都是重写了equals和hashCode方法的,不同的重写生成的hashCode有可能重复。

  但是他们重写的结果依然是:equals相等,hashCode就相等(看源码得出的结论)。一般来讲重写equals都需要重写一下hashCode。

  2.举例子:

  有了上面的结论,那么举个简单的例子,Java的集合框架中的Set<E>是无序不能重复的,那么如何判断Set中的元素重复性就是equals的问题。

  假设我们有一个User类:

  1. public class User {
  2. private String name;
  3. private String password;
  4. //get.set方法
  5. }

  现在把User的两个对象添加进一个Set<User>集合:

  1. Set<User> sets = new HashSet<User>();
  2. User u1 = new User("aaa", "aaa");
  3. User u2 = new User("bbb", "bbb");
  4. sets.add(u1);
  5. sets.add(u2);

现在需要再向sets里面添加一个和u1一样的元素,User u3 = new User("aaa", "aaa");你会发现可以添加进去,这是怎么回事呢,u1和u3不是一样吗,其实不是这样的,u1和u3在内存中的地址不一样(分别new出来的两个对象地址不同),那么我们重写User的equals方法,如下:(我们只判断用户名,只要name相等就相等,忽视password)

  1. @Override
  2. public boolean equals(Object obj) {
  3. if(obj == null) {
  4. return false;
  5. }
  6.  
  7. if(!(obj instanceof User)) {
  8. return false;
  9. }
  10.  
  11. if(this == obj) {
  12. return true;
  13. }
  14.  
  15. User u = (User)obj;
  16. if(!(this.name == null ? u.getName() == null : this.name.equals(u.getName()))) {
  17. return false;
  18. }
  19.  
  20. return true;
  21. }

再测试,发现u3还是能添加斤sets,这又是什么情况,不是说equals相等就是相同的元素,就不能添加进去吗,其实还有hashCode的原因。试想一下我现在sets里面只有u1和u2两个元素,当添加u3的时候,用u3跟u1和u2做equals比较,如果返回值为false就添加进去,如果为有一个为true就表示重复了,这样子是可行的,也是安全的,但是问题就在于如果我的sets里面已经有1w个User了呢,岂不是每一次添加新的User的时候都要比较1~10000次么,对于高并发的系统,这个是不允许的,性能太差。所以就有了hashCode,刚刚说道当sets里面存在u1和u2,当添加u3的时候,他要做遍历equals比较,其实Java不是这样做的,当添加u3的时候,JVM会先调用u3的hashCode方法,返回一个int数字,这个int数字上面说了,是映射一个内存地址,当sets在add u3的时候,他发现这块地址上面没有东西,那就直接添加进sets,不用比较,因为连内存中都不存在u3,那sets里面就肯定不存在了,根本不需要比较,但是,还有一种情况,就是当add u3的时候发现这块地址上面已经存在了一个u3,那是不是就意味着sets里面有u3了呢,答案是否定的,因为根据上面的规定,hashCode相等但是equals不一定相等,那么这时候就需要对sets里面的元素进行比较,如果返回值全都是false,就说明sets里面没有u3,那就添加进去,如果有一个返回值为true就说明已经存在了,就不添加进去,这样子性能就好很多。所以说就需要重写equals的同同时重写hashCode,并且保持一致性,前者相等,后者就必须相等,这是JDK规定,不然二者就没有什么意义了。于是重写hashCode,如下:

  1. @Override
  2. public int hashCode() {
  3. return this.name.hashCode();
  4. }

这样子就表示一个根据name重写,相同的name对应的hashCode一定是相同的。当比较到hashCode相同的时候直进行equals比较,而不同的时候直接添加。

这样一来,再添加name相同的两个User就一定添加不进去了。hashCode就是这样的原理。

浅析Java的HashCode,以及equals的更多相关文章

  1. java中hashcode()和equals()的详解

    今天下午研究了半天hashcode()和equals()方法,终于有了一点点的明白,写下来与大家分享(zhaoxudong 2008.10.23晚21.36). 1. 首先equals()和hashc ...

  2. 【Java】hashcode()和equals()

    大家知道,在集合中判断集合中的两个元素是否相同,依赖的是hashcode()和equals()两个方法. > 一个简单的实验 public class Teacher { private Int ...

  3. Java中hashcode,equals和==

    hashcode方法返回该对象的哈希码值. hashCode()方法可以用来来提高Map里面的搜索效率的,Map会根据不同的hashCode()来放在不同的位置,Map在搜索一个对象的时候先通过has ...

  4. java中hashcode和equals的区别和联系

    HashSet和HashMap一直都是JDK中最常用的两个类,HashSet要求不能存储相同的对象,HashMap要求不能存储相同的键. 那么Java运行时环境是如何判断HashSet中相同对象.Ha ...

  5. java 中hashcode和equals 总结

    一.概述            在Java中hashCode的实现总是伴随着equals,他们是紧密配合的,你要是自己设计了其中一个,就要设计另外一个.当然在多数情况下,这两个方法是不用我们考虑的,直 ...

  6. java的HashCode和equals

    什么时候用到hashcode,什么时候用到equals? 首先java为每个对象都生成有默认的hashcode,这个java core里说是java对象的内存地址,但是equals方法里比较的也是对象 ...

  7. 【JAVA】hashcode() & equals()

    平时使用map时都是用JAVA原生的类型,所以很少关注到hashcode()和equals()的方法的内部实现.近期实现一个小工具,涉及到自己写的类的查找比对,又再次重温了相关的知识. 上简单示例代码 ...

  8. java中 hashCode() 和 equals()

    1. 值类型是存储在内存中的栈,而引用类型的变量在栈中仅仅是存储引用类型变量的地址来自堆,而其本身则存储在栈中. 2. ==操作比较的是两个变量的值是否相等, 3. 对于引用型变量表示的是两个变量在堆 ...

  9. 深入探究Java中hashCode()和equals()的关系

    目录 一.基础:hashCode() 和 equals() 简介 equals() hashCode() 二. 漫谈:初识 hashCode() 与 equals() 之间的关系 三. 解密:深入理解 ...

随机推荐

  1. Alloc and release

    https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractic ...

  2. iOS添加自动更新的代码

    - (void)versionUpdate{ //获得当前发布的版本 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_ ...

  3. c# Start/Stop/Check Status远程计算机的Windows Service

    static void Main(string[] args) { ConnectionOptions op = new ConnectionOptions(); // 登陆远程计算机的远程, op. ...

  4. python入门到精通[一]:搭建开发环境

    摘要:Python认识,及在windows和linux上安装环境,测试是否安装成功. 1.写在前面 参加工作也有5年多了,一直在做.net开发,近一年有做NodeJS开发.从一开始的不习惯,到逐步适应 ...

  5. Groupon面经Prepare: Max Cycle Length

    题目是遇到偶数/2,遇到奇数 *3 + 1的题目,然后找一个range内所有数字的max cycle length.对于一个数字,比如说44,按照题目的公式不停计算,过程是 44, 22, 11, 8 ...

  6. HUD 5086 Revenge of Segment Tree(递推)

    http://acm.hdu.edu.cn/showproblem.php?pid=5086 题目大意: 给定一个序列,求这个序列的子序列的和,再求所有子序列总和,这些子序列是连续的.去题目给的第二组 ...

  7. qsort函数用法

    qsort函数用法   qsort 功 能: 使用快速排序例程进行排序 用 法: void qsort(void *base, int nelem, int width, int (*fcmp)(co ...

  8. poj 1417(并查集+简单dp)

    True Liars Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 2087   Accepted: 640 Descrip ...

  9. Ini文件操作函数

    /// <summary> /// Copies a string into the specified section of an initialization file. /// &l ...

  10. codevs 1202 求和

    http://codevs.cn/problem/1202/ 1202 求和  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 青铜 Bronze 题解       题目描述 D ...