ava中的数据类型,可分为两类:
1.基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean
他们之间的比较,应用双等号(==),比较的是他们的值。
2.复合数据类型(类)
当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。 JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地 址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号(==)进行比较的,所以比较后的结果跟双等号(==)的结果相同。

public boolean equals(Object obj) { return (this == obj); }

如果对象没有覆写equals方法默认使用Object方法,就是比较对象的内存地址是否一样。

若某个类没有覆盖equals()方法,当它的通过equals()比较两个对象时,实际上是比较两个对象是不是同一个对象。这时,等价于通过“==”去比较这两个对象
注意点:

如果类没有重写equals,那么对于该类的对象来说“==”和“equals”没有区别。都是比较对象的内存地址。 但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。所以会有很多经典的面试题:

String a = new String ("abc");
String b = new String ("abc");
System.out.println(a.equals(b));
System.out.println(a==b);

返回值是true和false

String以及基本数据类型的包装类中都重写了hashCode()方法,他们生成的哈希码是跟他们的内容
(这里就是指值)息息相关,也就是说在用equals()比较两个变量是否相等的时候只要他们的值相等,那么就返回true

第二:我们可以覆写覆盖equals()方法。则通过equals()比较该类的两个对象是否相等,但是需要注意的一点如果你重写equals()方法,那么你必须重写hashCode()方法

从开始学习Java,哈希码以及equals和==的区别就一直困扰着我。
要想明白equals和==的区别首先应该了解什么是哈希码,因为在jdk的类库中不管是object实现的equals()方法还是String重写的equals()方法以及
其它基本数据类型的包装类重写的euqals()方法,他们在比较对象的时候都是根据hashCode()方法返回的哈希码来判断两个对象是否相等的,所以要想搞清楚
equals()就必须要知道什么是哈希码。
那么究竟是什么哈希码呢?哈希码是可以根据的自己的需求,采用不同的算法产生的一个Int型数字。Object的hashCode()方法返回的哈希码是根据对
象的内存地址来生成的,所以每个对象的哈希码是不相同的,如果你要比较的两个变量的类型没有重写Object的hashCode()方法那么这两个变量除非是指向
相同的对象(地址相同),否则返回的一定是false。而String以及基本数据类型的包装类中都重写了hashCode()方法,他们生成的哈希码是跟他们的内容
(这里就是指值)息息相关,也就是说在用equals()比较两个变量是否相等的时候只要他们的值相等,那么就返回true,因为他们生成的哈希码相等。有个
值得注意的地方是:在JDK的类中只要重写的Object的equals()方法,那就肯定重写了它的hashCode()方法,因为equals()方法中在比较两个变量时,
判断的标准就是哈希码是否一样,Object中的hashCode()方法是根据对象的内存地址生成的,如果重写了equals()方法而继续使用原来的hashCode()方
法生成的哈希码作为判断相等的依据,那显然达不到我们要改变判断对象是否相等的标准的效果。
既然知道了什么是哈希码,现在就可以说明equals()和==的区别了,对于没用重写Object的equals()方法的类型所生成的对象的比较,equals()
和==是效果一样的,==比较的是两个变量所指向的对象在内存中指向的地址是否一样,而当两个变量的类型中继承了Object的equals()方法的时候,由于
该方法比较的标准是看哈希码是否相等,而哈希码是由hashCode()方法生成的,该方法生成哈希码的依据是对象在内存中的地址,最终比较的还是地址。所
以说equals()和==效果一样。而对于像String和那些基本数据类型的包装类来说equals()和==就不一样了,因为他们重写了Object的equals()方法和
hashCode()方法,使得equals()方法的判断标准发生了改变,他们的判断标准是看对象的内容是否相等,这里就是指值是不是一样,因为他们的哈希码是
根据对象的值生成的,与内存地址无关了,所以他们的equals()方法比较的是对象的值是否相等,而==比较的仍然是地址。所以equals()和==就不一样了。
这里还要注意一下,在比较值的时候,一般==比较的是基本数据类型,而equals()比较的是引用数据类型,地址相同一定值相等,而值相等地址不一定
相同。如果比较的是地址,那最好是用==,因为无论是否重写了Object的equals()方法,==永远比较的是地址,equals()比较的是哈希码,而哈希码生成
的标准是由类作者自己根据需求来控制的。

结论2:

1、如果两个对象相同,那么它们的hashCode值一定要相同;2、如果两个对象的hashCode相同,它们并不一定相同 ,上面说的对象相同指的是用eqauls方法比较。反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等
如果两个对象x和y满足x.equals(y) == true,它们的哈希码(hash code)应当相同。Java对于eqauls方法和hashCode方法是这样规定的:(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;(2)如果两个对象的hashCode相同,它们并不一定相同

1、如果两个对象相等,那么它们的hashCode()值一定相同。
这里的相等是指,通过equals()比较两个对象时返回true。

2.、如果两个对象hashCode()相等,它们并不一定相等。
因为在散列表中,hashCode()相等,即两个键值对的哈希值相等。然而哈希值相等,并不一定能得出键值对相等。补充说一句:“两个不同的键值对,哈希值相等”,这就是哈希冲突。

我们来看下面的例子

HashSet (需要重写hashCode和equals方法)

一般描述的事物需要往集合中添加,那么都需要重写这两个方法
删除和判断元素是否存在,都是先判断hashCode 看看是否存在,若存在则继续equals();

import java.util.*;
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name=name;
this.age=age;
}
public int hashCode()//重写
{
return name.hashCode()+age ;
}
public boolean equals(Object obj)//重写 Object不能换
{
if(!(obj instanceof Person))
return false;
Person p=(Person)obj; System.out.println(this.name+"...."+p.name); return this.name.equals(p.name)&&this.age==p.age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class HashSetDemo
{
public static void main(String[] args)
{
HashSet hs=new HashSet(); hs.add(new Person("lisi01",30));
hs.add(new Person("lisi02",33));
hs.add(new Person("lisi03",35));
hs.add(new Person("lisi02",33));
hs.add(new Person("lisi01",30));
hs.add(new Person("lisi04",32));
hs.add(new Person("lisi03",35)); Iterator it=hs.iterator(); while(it.hasNext())
{
Person p=(Person)it.next();;
sop(p.getName()+" "+p.getAge());
}
}
public static void sop(Object obj)
{
System.out.println(obj); }
}

参考案例2:

第一:
Set集合没有顺序,也不允许重复。
为什么要这样:模拟现实的集合。
这里的重复只是:对象的重复
何为对象的重复:指的就是同一个对象。
何为同一个对象:内存中,所在的内存编号一致。
内存编号的表示是什么:哈希码(哈希码一般是 类名 和 对象所在内存地址的十六进制数字表示 的组合)。
第二:
这种设置和实现中的矛盾在什么地方:
现实生活中只要属性相同,我们就认为那是同一个对象。
这与计算机比较同一个对象的方法不同(计算机使用内存地址,即哈希码)
于是,就需要重写equals方法和hashCode方法(&&)来让程序的运行结果符合现实生活
基本数据类型的实现类都已经重写了上面的两个方法。
第三:
为什么要重写equals方法和hashCode方法(技术实现原理):
程序向HashSet中添加一个对象时,先用hashCode方法计算出该对象的哈希码。
比较:
(1),如果该对象哈希码与集合已存在对象的哈希码不一致,则该对象没有与其他对象重复,添加到集合中!
(2),如果存在于该对象相同的哈希码,那么通过equals方法判断两个哈希码相同的对象是否为同一对象(判断的标准是:属性是否相同)
1>,相同对象,不添加。
2>,不同对象,添加!
这时有两个疑问:
1,为什么哈希码相同了还有可能是不同对象?
2,为什么经过比较哈希码还需要借助equals方法判断?

答:
首先:
按照Object类的hashCode方法,是不可能返回两个相同的哈希码的。(哈希码唯一标志了对象)
然后:
Object类的hashCode方法返回的哈希码具有唯一性(地址唯一性),但是这样不能让程序的运行逻辑符合现实生活。(这个逻辑就是:属性相同的对象被看作同一个对象。)

为了让程序的运行逻辑符合现实生活,Object的子类重写了hashCode的方法(基本数据类型的实现类都已经重写了两个方法,自定义的类要软件工程 师自己重写。)

那么:
重写的宗旨是什么?
重写就是为了实现这样的目的:属性相同的不同对象在调用其hashCode方法后,返回的是同样的哈希码。
但是
我们在重写的时候,发现几乎所有的写法都无法避免一个bug:有一些属性不同的对象(当然是不同的对象),会返回相同的哈希码。(即 重码)

最后:
为了解决这个问题:在哈希码相同的时候,再用equals方法比较两个对象的对应属性是否相同,这样,确保了万无一失。
这样:上面两个问题得到解决。
5
下面给出一个属性不同但哈希码相同的例子:

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
class Person {
private String name;
private int id;
Person(String name,int id) {
this.name = name;
this.id = id;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setId(int id){
this.id = id;
}
public int getId(){
return id;
}
public int hashCode(){
return name.hashCode()+id; //使用字符串哈希值与Integer的哈希值的组合
//这样会产生重码,实际上重码率很高
}
public boolean equals(Object obj){
if(obj instanceof Person){ //
Person p = (Person)obj;
return(name.equals(p.name) && id == p.id);
}
return super.equals(obj);
}
}
public class TestHashSet2 {
public static void main(String[] args) {
Person p1 = new Person("a",1);
Person p2 = new Person("b",0);
Set<Person> set = new HashSet<Person>();
set.add(p1);
set.add(p2);
Iterator<Person> it = set.iterator();
while(it.hasNext()){
System.out.println(it.next().getName());
}
}
}
  • 总思路:hashCode不同时,则必为不同对象。hashCode相同时,根据equlas()方法判断是否为同一对象。
  • 在HashSet,HashMap,HashTable中都存在该问题。
												

java中“”==“” equals hashcode的关系的更多相关文章

  1. 浅谈Java中的hashcode方法以及equals方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个 ...

  2. K:java中的hashCode和equals方法

      hashCode和equals方法是Object类的相关方法,而所有的类都是直接或间接的继承于Object类而存在的,为此,所有的类中都存在着hashCode和equals.通过翻看Object类 ...

  3. 关于java中的hashcode和equals方法原理

    关于java中的hashcode和equals方法原理 1.介绍 java编程思想和很多资料都会对自定义javabean要求必须重写hashcode和equals方法,但并没有清晰给出为何重写此两个方 ...

  4. java中equals和hashCode方法随笔二

    前几天看了篇关于java中equals和hashCode方法的解析 1.Object类中的equals方法和hashCode方法. Object类中的equals和hashCode方法简单明了,所有的 ...

  5. Java中equals和hashcode的区别?

    Java中equals和hashcode方法是在Object对象中的,所以每个对象都有这两个方法,大多数时候我们为了实现特定需求需要重写这两个方法 equals和hashcode方法常用在同一个类中用 ...

  6. java中equals和==的区别 (转)

    java中equals和==的区别  值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中. ==操作比较的是两个变量的值是否相等,对于引 ...

  7. 浅谈Java中的hashcode方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: 1 public native int hashCode(); 根据 ...

  8. java中的hashcode

    hashcode的作用 对于包含容器类型的程序设计语言来说,基本上都会涉及到hashCode.在Java中也一样,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括 ...

  9. 【转】浅谈Java中的hashcode方法(这个demo可以多看看)

    浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...

随机推荐

  1. C# 根据BackgroundWoker异步模型和ProgressBar控件,自定义进度条控件

    前言 程序开发过程中,难免会有的业务逻辑,或者算法之类产生让人能够感知的耗时操作,例如循环中对复杂逻辑处理;获取数据库百万乃至千万级数据;http请求的时候等...... 用户在使用UI操作并不知道程 ...

  2. matlab单目相机标定——标定步骤以及参数含义

    参考博客园的一篇文章: https://www.cnblogs.com/flyinggod/p/8470407.html#commentform

  3. echo改变字体颜色

    格式: echo -e "\033[字背景颜色;字体颜色m字符串\033[0m" 例如: echo -e "\033[41;36m something here \033 ...

  4. 附021.Traefik-ingress部署及使用

    一 Helm部署 1.1 获取资源 [root@master01 ~]# mkdir ingress [root@master01 ~]# cd ingress/ [root@master01 ing ...

  5. 可以Postman,也可以cURL.进来领略下cURL的独门绝技

    文章已经收录在 Github.com/niumoo/JavaNotes ,更有 Java 程序员所需要掌握的核心知识,欢迎Star和指教. 欢迎关注我的公众号,文章每周更新. cURL 是一个开源免费 ...

  6. Pycharm激活码测试有效,测试时间:2020-1-14可用

    812LFWMRSH-eyJsaWNlbnNlSWQiOiI4MTJMRldNUlNIIiwibGljZW5zZWVOYW1lIjoi5q2j54mIIOaOiOadgyIsImFzc2lnbmVlT ...

  7. java实现人民币金额大写

    在与财务相关的应用中,经常会用到人民币金额的大写,比如发票的打印程序. 本题的任务是:从键盘输入一个十亿以内的正整数(int类型),把它转换为人民币金额大写(不考虑用户输入错误的情况). 比如,用户输 ...

  8. JDBC连接泄露问题的排查过程总结

    当前使用的Spring JDBC版本是5.0.0.RC1,HikariCP版本是3.1.0. 今天测试同学反馈在前端页面点击次数多了,就报500错误,数据显示不出来.于是我在后台服务日志中观察发现Hi ...

  9. zabbix 监控 tcp 连接数

    一.zabbix-agent 服务器配置 1.编辑zabbix_agent配置文件,添加以下内容 vim /etc/zabbix/zabbix_agentd.conf ##添加此行 UserParam ...

  10. zabbix通过Web场景监控URL

    选择主机添加应用集       添加Web监控 选在相应主机,并添加Web监控 按照方式新建Web场景 注意: 名称统一规则:相应的域名 应用集:选择之前创建的 或者 新建一个,名称为“URL 告警” ...