基本概念

  • ==是运算符,比较的是两个变量是否相等;
  • equals()是Object方法,用于比较两个对象是否相等

看一下源码:

  1. public boolean equals(Object anObject) {
  2. if (this == anObject) {
  3. return true;
  4. }
  5. if (anObject instanceof String) {
  6. String anotherString = (String)anObject;
  7. int n = value.length;
  8. if (n == anotherString.value.length) {
  9. char v1[] = value;
  10. char v2[] = anotherString.value;
  11. int i = 0;
  12. while (n-- != 0) {
  13. if (v1[i] != v2[i])
  14. return false;
  15. i++;
  16. }
  17. return true;
  18. }
  19. }
  20. return false;
  21. }

当this==anObject的时候,返回true,即this 和 obj引用同一个对象时,才会返回true;

还有就是当判断字符串相等的时候,当anObject是String类型,并且长度和内容一样的时候,返回true;

小结

只有当引用一个对象的时候,才会返回true。

而我们在实际用equals()方法的时候,我们往往不是为了判断两个引用的是一个对象,因此我们此时要重写equals()方法;

equals()有以下的公约必须遵守:

  • 对称性:x,y非空,如果x.equals(y)返回true,那么y.equals(x)必为true;
  • 自反性:对于任何非null的引用值x,x.equals(x)必须返回true;
  • 传递性:x,y,z非空,x.equals(y),y.equals(z)返回true,那么x.equals(z)必为true;
  • 一致性:x,y非空,只要对象信息没有被修改,那么多次调用x.equals(y)的结果肯定都一样;
  • 对于任何非null的引用值x,x.equals(null)必须返回false;
因此,我们一般有以下推论:
  • 任何情况下,x.equals(null),永远返回是false;x.equals(和x不同类型的对象)永远返回是false。
  • equals()相等的两个对象,hashcode()一定相等;反过来:hashcode()不等,一定能推出equals()也不等;
  • hashcode()相等,equals()可能相等,也可能不等
现在我们可以这样解释了:

1、因为是按照hashCode来访问小内存块,所以hashCode必须相等。

2、HashMap获取一个对象是比较key的hashCode相等和equal为true。

3、比如对象ObjectA和ObjectB他们都有属性name,那么hashCode都以name计算,所以hashCode一样,但是两个对象属于不同类型,所以equal为false。所以hashCode相等,却可以equal不等

当我们编写完成了equals()方法的时候,我们要问自己三个问题:它是否是对称的、传递的、一致的;

问题:重写equals()方法的时候总要重写hashcode()方法,为什么要重载equal方法?

在每个重写equals()的类中,我们必须重写hashcode()方法;如果不这样做,会违反hashcode()的公约:

  • 1.只要对象的信息没有改变,那么对一个对象调用多次,hashcode()方法都必须始终如一的返回同一个整数;
  • 2.如果两个对象根据equals()方法比较是相等的,那么调用这两个对象中任意一个对象的hashcode()方法都必须产生同样的结果;
  • 3.如果两个对象根据equals()方法比较是不相等的,那么调用这两个对象中任意一个对象的hashcode()方法不一定产生同样的结果;

相等的对象必须有相同的散列码

代码示例

  1. import java.util.HashSet;
  2. import java.util.Set;
  3.  
  4. /**
  5. * hashcode和equals方法
  6. * HashMap中有一个put方法,put(key,value)key是无序不可重复的
  7. */
  8. public class SetTest2 {
  9. public static void main(String[] args)
  10. {
  11. //创建集合
  12. Set es = new HashSet();
  13.  
  14. Employee e1 = new Employee("1000","tao");
  15. Employee e2 = new Employee("1000","tao");
  16. // Employee e2 = new Employee("1001","tao1");
  17. Employee e3 = new Employee("1002","tao2");
  18. Employee e4 = new Employee("1003","tao3");
  19. Employee e5 = new Employee("1004","tao4");
  20. Employee e6 = new Employee("1005","tao5");
  21. // System.out.println(e1.equals(e2));
  22. // System.out.println(e2);
  23. System.out.println(e1.hashCode());
  24. System.out.println(e2.hashCode());
  25. es.add(e1);
  26. es.add(e2);
  27. es.add(e3);
  28. es.add(e4);
  29. es.add(e5);
  30. es.add(e6);
  31.  
  32. System.out.println(es.size());
  33. }
  34. }
  35.  
  36. class Employee{
  37. String num;//员工编号
  38. String name;
  39.  
  40. Employee(String num,String name){
  41. this.num = num;
  42. this.name = name;
  43. }
  44. //重写equals方法,如果员工编号相同并且名字相同,则是同一个对象
  45. public boolean equals(Object o){
  46. if (this == o){
  47. return true;
  48. }
  49. if (o instanceof Employee){
  50. Employee e = (Employee) o;
  51. if (e.num.equals(this.num) && e.name.equals(this.name))
  52. {
  53. return true;
  54. }
  55. }
  56. return false;
  57. }
  58. //重写Hashcode方法
  59. public int hashCode(){
  60. //以员工编号分组,可散列均匀分布
  61. return num.hashCode();
  62. }
  63. }
  64. hashCode()的底层实现:
  65.  
  66. public int hashCode() {
  67. int h = hash;
  68. if (h == 0 && value.length > 0) {
  69. char val[] = value;
  70.  
  71. for (int i = 0; i < value.length; i++) {
  72. h = 31 * h + val[i];
  73. }
  74. hash = h;
  75. }
  76. return h;
  77. }

可以看到最终hash = s[0]31^(n-1) + s[1]31^(n-2) + ... + s[n-1];

涨知识:equals 和 == 你真的了解吗?的更多相关文章

  1. Java易混小知识——equals方法和==的区别

    一.equals方法和==的区别 1.equals是String对象的方法,可以通过".“调用. 2.== 是一个运算符. 二.常用的比较用法 1.基本数据类型比较. equals和==都比 ...

  2. 涨知识Style

    1.用Access作为后台数据库支撑,书写一个C#写入记录的案例 示例1: using System.Data.OleDb; string sql = "insert into 表 (列1, ...

  3. Camel——涨知识了,骆驼命名法

    骆驼式命名法(Camel-Case)又称驼峰命名法,是电脑程式编写时的一套命名规则(惯例).正如它的名称CamelCase所表示的那样,是指混合使用大小写字母来构成变量和函数的名字.程序员们为了自己的 ...

  4. 涨知识,涨知识 :ThinkPHP框架下Where条件查询Mysql数据库某字段是否为空

    代码虐我千百遍,我对代码如初恋~ 问题: 查询某字段app_date数据是否为NULL,正常我们实现的办法是: $map['app_data'] = array('eq','null'); $data ...

  5. main方法原来只要放在public static类中就能跑,涨知识了

    接口中可以装在嵌套类对象. public interface ClassInterface { void howdy(); class Test implements ClassInterface { ...

  6. 你可能不知道的 10 条 SQL 技巧,涨知识了!

    转自:http://mp.weixin.qq.com/s?__biz=MjM5NzM0MjcyMQ==&mid=2650076293&idx=1&sn=38f6acc759df ...

  7. 涨知识-VI 基于TCP/UDP的应用层协议

    基于TCP/UDP的应用层协议: 基于TCP: Telnet(Teletype over the Network, 网络电传),通过一个终端(terminal)登陆到网络 FTP(File Trans ...

  8. 涨知识 --- VI

    1.空类所占空间大小 空类所占空间为1,单一继承的空类空间也为1,多继承的空类空间还是1.但是虚继承涉及虚表(虚指针),所以sizeof(C)的大小为4. 2.内联函数与宏定义 Ans:内联函数和普通 ...

  9. 涨知识---V

    1.内存对齐 在解释内存对齐的作用前,先来看下内存对齐的规则: 1).  对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据成员的偏移量必须是min(#pragma pack()指定的数, ...

随机推荐

  1. ceph Luminous版手动安装零散记录

    1.安装必要的依赖包,关防火墙,向/etc/hosts内添加域名等 2.安装ceph 配置yum源 (如果嫌慢,可以配置cachedir=/home/yum/$basearch/$releasever ...

  2. NopCommerce 更改发票字体

    NopCommerce 默认是用~/App_Data/Pdf/FreeSerif.ttf 这个字体的. 用这个字体,发票里的中文不能显示. 可以把c:\windows\font\simhei.ttf  ...

  3. rest_framework 之视图

    1. 继承ModelSerilizer,直接指定要序列化的表模型 MySerializers.py from app import models # 继承ModelSerilizer,直接指定要序列化 ...

  4. 浮点型的三个特殊值 Double.NEGATIVE_INFINITY Double.POSITIVE_INFINITY Double.NaN

    Double.NEGATIVE_INFINITY 负无穷 Double.POSITIVE_INFINITY 正无穷 Double.NaN 非数 注意:浮点数才有无穷的概念,整数是没有的 比如: int ...

  5. Zabbix4.0报警配置-企业微信报警

    一:前期准备 1.1:企业号注册 https://qy.weixin.qq.com/  微信调用接口说明 http://qydev.weixin.qq.com/wiki/index.php?title ...

  6. HTTP,RFC自学心得

    HTTP协议描述的是:发送方与接收方的通信协议,通过两方的自觉遵守而存在,当然有不少的浏览器并没有百分百遵守这份协议. HTTP是运行于应用层的协议,基于TCP协议而运作.基本上是客户/服务器对答模式 ...

  7. My SQL随记 002 登陆

    如何启动MySQL服务 Step1 我的电脑右键属性找到 控制面板 选择 系统和安全 Step2 管理工具中找到服务 Step3 找到你的MySQL启动服务 如何通过黑窗口登陆退出 MySQL Ste ...

  8. Delphi xe8 FMX StringGrid根据内容自适应列宽。

    Delphi xe8 FMX StringGrid根据内容自适应列宽. 网上的资料比较复杂,而且不是根据字体字号等设置列宽.故自己写了个function来用. function GetColMaxDa ...

  9. git不添加.idea等IDE配置文件夹

    git不添加.idea等IDE配置文件夹由于.idea(intellJ,pycharm)的IDE文件夹很常出现,建议将gitignore设置为全局. git config --global core. ...

  10. 将GETDATE()转换为指定日期格式的varchar类型

    CREATE FUNCTION [dbo].[FormatDate] (@date as datetime, ) ) ) AS BEGIN ) set @datestring=@formatstrin ...