基本概念

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

看一下源码:

 public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}

当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()方法不一定产生同样的结果;

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

代码示例

import java.util.HashSet;
import java.util.Set; /**
* hashcode和equals方法
* HashMap中有一个put方法,put(key,value)key是无序不可重复的
*/
public class SetTest2 {
public static void main(String[] args)
{
//创建集合
Set es = new HashSet(); Employee e1 = new Employee("1000","tao");
Employee e2 = new Employee("1000","tao");
// Employee e2 = new Employee("1001","tao1");
Employee e3 = new Employee("1002","tao2");
Employee e4 = new Employee("1003","tao3");
Employee e5 = new Employee("1004","tao4");
Employee e6 = new Employee("1005","tao5");
// System.out.println(e1.equals(e2));
// System.out.println(e2);
System.out.println(e1.hashCode());
System.out.println(e2.hashCode());
es.add(e1);
es.add(e2);
es.add(e3);
es.add(e4);
es.add(e5);
es.add(e6); System.out.println(es.size());
}
} class Employee{
String num;//员工编号
String name; Employee(String num,String name){
this.num = num;
this.name = name;
}
//重写equals方法,如果员工编号相同并且名字相同,则是同一个对象
public boolean equals(Object o){
if (this == o){
return true;
}
if (o instanceof Employee){
Employee e = (Employee) o;
if (e.num.equals(this.num) && e.name.equals(this.name))
{
return true;
}
}
return false;
}
//重写Hashcode方法
public int hashCode(){
//以员工编号分组,可散列均匀分布
return num.hashCode();
}
}
hashCode()的底层实现: public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value; for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}

可以看到最终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. sql语句查询结果合并union all用法

    整理别人的sql 大概的思想是用union 和union all --合并重复行select * from Aunion select * from B --不合并重复行select * from A ...

  2. squid代理

    概念    高性能dialing服务软件,作为前置缓存服务,用于替代用户向网站服务器请求页面数据并进行缓存.    默认占用端口3128.3401.4827    分类    从作用分类       ...

  3. 初始C#(二)

    一 数组 定义:能存放任意多个同类型数据 声明与赋值:声明:数据类型[ ]变量名                                        赋值:变量名=new 数据类型[长度] ...

  4. 关于数据安全RSA,MD5,TOKEN

    网络上明文传输时 1.数据可能被窃取:2.数据可能被篡改:3.数据被泄露 如何解决: 1.数据被窃取是由于数据能随意的被拿到,且能够被识别.可以有2个方式解决 a.使数据不能随意被获取: 使用toke ...

  5. Java语法基础学习DayEighteen(常用类)

    一.String类 1.特点 String代表不可变的字符序列,底层用char[]存放. String是final的. 2.内存解析 3.常用方法 int length() char charAt(i ...

  6. ef core中如何实现多对多的表映射关系

    文档:https://docs.microsoft.com/en-us/ef/core/modeling/relationships class MyContext : DbContext { pub ...

  7. java面向对象编程(一)-类与对象

    1.问题的提出      张老太养了两只猫猫:一只名字叫小白,今年3岁,白色.还有一只叫小花,今年100岁,花色.请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色.如果用户输入的小 ...

  8. CentOS上升级gcc编译器使支持C++11

    首先向博主致敬,好的东西拿来共享了,用一下不错. https://blog.csdn.net/clirus/article/details/62424517 0. 目标  最近在学习c++11,我本机 ...

  9. 蓝牙协议分析(10)_BLE安全机制之LE Encryption

    1. 前言 前面文章介绍了两种BLE的安全机制:白名单[4]和LL privacy[3].说实话,在这危机四伏的年代,这两种“捂着脸讲话(其它人不知道是谁在讲话,因而不能插话.不能假传圣旨,但讲话的内 ...

  10. 蓝牙协议分析(4)_IPv6 Over BLE介绍

    1. 前言 蓝牙是个奇葩的家伙:它总是以后来者的身份出现,很喜欢打仗,而且还不落下风(有点像某讯的风格).90年代末期和Wi-Fi的无线标准之争如此,当前和802.15.4系(ZigBee.RF4CE ...