== 、equals、哈希值、地址知识整理

== 、equals、哈希值、地址知识整理,第1张

一、== 和 equals() 简述

我们Java中常说的判断相等有两种:== 和 equals方法。

应用范围:

我们常将 == 用于基本类型的判断,equals常用于引用类型的判断。

判断原理:

== :Java中会先判断他们的哈希值,哈希值相同时,再对其地址进行判断,地址相同返回true。其实这里很多人会说先去判断相不相等,其实在哈希值就是根据不同的规则生成的,一般情况都与值是密切相关的。

equals : 在引用类型判断时,我们使用它,两值判断哈希值相同就返回true,不用比较地址。

二、哈希值 == 地址?

废话不多说,直接上题目:

String s = "1";
String s2 = "1";
String s3 = "12";
String s4 = s + "2";
System.out.println(s == s2);
System.out.println(s3 == s4);
System.out.println(s.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
System.out.println(s4.hashCode());

1、  判断 s == s2 结果为true|false?

2、判断 s3 == s4 结果为true|false?

3、判断 s.hashCode() == s2.hashCode() 结果为true|false?

4、判断 s3.hashCode() == s4.hashCode() 结果为true|false?

好了,上结果:

String s = "1";
String s2 = "1";
String s3 = "12";
String s4 = s + "2";
System.out.println(s == s2);//true
System.out.println(s3 == s4);//false
System.out.println(s.hashCode() == s2.hashCode());//true
System.out.println(s3.hashCode() == s4.hashCode());//true

System.out.println(s.hashCode());//49
System.out.println(s2.hashCode());//49

System.out.println(s3.hashCode());//1569
System.out.println(s4.hashCode());//1569

可以看到,

第一个结果s和s2的哈希值一样,他们返回true,说明他们地址也是一样的。也就是说在常量的赋值过程中,Java会自动默认在你存储新的变量时根据hash值分配统一地址,这样就可以大大避免内存的浪费。

第二个结果s3和s4的哈希值也是一样的,但返回的却是false,再次验证 == 是判断地址是否相同的,同样我们也可以得到一个结论:哈希值和地址并不是一个东西,他们有自己各自的分配和实现体系。

三、哈希值生成原理

其实在Java的类中,并没有完全规定死所有的哈希值生成规则。所以我们在创建Javabean的时候,总能看到这个方法。

所以我们常见的Javabean中其实我们可以自己去设置简易的规则,这两个方法主要是根据你的选择来生成不同的判断相等的形式。

如果你没有重写这两个方法,系统有默认的方法。

例:

class Person{
    private int id;
    private String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

对上面的Person类没有重写方法,结果

可以看到,即便构造函数参数一样,每次new 对象的时候都会生成一个不同的哈希值。

当我们重写方法时只用名字来作为区别:

 

class Person{
    private int id;
    private String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

由此,也算是我们以自己的方式来选择生成不同情况的hash值。所以我们常用类像包装类,在他们的原码中也都有相应的重写了的规则,大家有想法的可以去看看。

这里将的是我们自己类生成规则,我们再来看一个我们最常用的String类的哈希值生成规则吧:

其实,String的生成规则很简单,相信眼尖的大家在最开始的时候就已经看出来了:

String s = "1";
String s2 = "1";
String s3 = "12";
String s4 = s + "2";

System.out.println(s.hashCode());//49
System.out.println(s2.hashCode());//49

System.out.println(s3.hashCode());//1569
System.out.println(s4.hashCode());//1569

如果对ASSIC码熟悉的已经看出来了,1的ASSIC码正是49.。所以首先我们就知道字符串的哈希值是与字符的ASSIC码有关系的。具体是什么关系呢?

“1” 的 hashCode 是 49

“12” 的 hashCode 是 1569

“12”刚好是“1”的49 *31 +“2” 的50 =1569,对不对呢?

我们再推测一下,a的ASSIC码是97 ,b的ASSIC码是98,

所以“ab”应该是 97*31+98 = 3007+98 = 3105,是不是呢?

没错,是这样的。

好了,总结一下,哈希值和地址并不是指同一个东西。哈希值主要是针对你要存的目标值进行,而地址就是指在内存中的唯一位置。在Java中二者相辅相成,大大提高数据的 *** 作效率。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/720003.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-25
下一篇 2022-04-25

发表评论

登录后才能评论

评论列表(0条)

保存