您当前的位置: 首页 >  Java

星拱北辰

暂无认证

  • 0浏览

    0关注

    1205博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【Java】浅析equals()和hashCode()

星拱北辰 发布时间:2020-03-07 11:02:21 ,浏览量:0

总览equals( ) 方法
  • 理解equals()方法和==运算符的区别是非常重要的。

    • 默认情况下(即没有被重写时)equals()只能比较引用类型,"=="既能 比较引用类型又能比较基本类型。
    • equals()方法从Object类继承,即比较对象引用的值
    • 一般都被子类方法覆盖,不再比较引用的值
  • "=="运算符:

    • 比较基本数据类型:相当于算术等号。
    • 比较引用数据类型:比较引用的值,不能被覆盖。
  • 通常情况,子类要重写equals( ),改变它的含义。所以有的类中 equals( )是比较地址,有的类中该方法就不比较地址,具体的,就看子类新定义的该方法的规定。建议看看包装类中的equals()方法,蛮有趣的。

  • 在Java中有个规定:如果equals( )返回两个对象是相等的,那这两个对象上调用hashCode( )返回的整数必须相等。否则在使用Hash类型集合时就会产生错误。

  • 注意:覆盖equals( )方法同时,还要记得覆盖hashCode( )方法。 需要说明,如果equals( )返回两个对象不等,它们的hashCode( )也 可以返回相同的整数。但是最好让它们的hashCode( )返回不同的整 数,这有利于提高Hash类型集合的性能。

  • 重写equals方法时,一定要重写hashcode()方法吗?

    • hashcode的调用的条件:

      • 想往map里面放一个类作为map的键值,这个类又是自己设计的;
      • 虽然类不是自己写的,但是你修改了这个类的equals方法;
    • 如果满足上述调用条件,就要注意重写hashcode方法。 这样 当你往map 里放值得时候,系统会调用这个对象的.hashcode()方法来生成相应的 hash值,来映射相应的对象。

  • 如果同一个类的两个对象的属性值相等,那么他们的hashcode一定相等吗?这个要看你具体如何实现你的hashcode,如果你希望他们的值一样hashcode也一样,你就可以这样实现。 但是hashcode的实现,一般要满足几个特征,比如自反性、对称性、传递性那些。

等价关系与equals( )

离散数学的知识:

设R是A上关系,若R是自反的、对称的和传递的,则称R是A中的等价关系。 若 a , b ∈ A ,且 a R b ,则称 a 与 b 等价 若 a,b\in A,且aRb,则称a与b等价 若a,b∈A,且aRb,则称a与b等价。

equals() 其实就是一种等价关系,它指定了某种方法(默认的hashCode()、重写的hashCode()、自定义的equals()判据等)来判定这种等价关系。

我们自己想要重写equals(),为了保证这种等价关系,就需要维护自反性、对称性、传递性。

其实,简单的测试还不太够,最好是有形式化的证明。

这篇文章中就涉及了equals()的自反性、对称性、传递性,做了简单的测试。

IDE自动生成equals( )和hashCode( )

如果你确实懒得重写equals()和hashCode(),IDE支持自动生成这两个方法。

首先,Person类已经完成到了这个程度:

import java.io.Serializable;

public class Person implements Serializable {

    private static final long serialVersionUID = 1L;

    private Integer id;

    private String name;

    private Integer age;

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

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}';
    }

}
Eclipse

在这里插入图片描述 在这里插入图片描述

import java.io.Serializable;
import java.util.Objects;

public class Person implements Serializable {

    private static final long serialVersionUID = 1L;

    private Integer id;

    private String name;

    private Integer age;

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

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}';
    }

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

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof Person)) {
            return false;
        }
        Person other = (Person) obj;
        return Objects.equals(id, other.id) && Objects.equals(name, other.name);
    }

}
IntelliJ IDEA

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

import java.io.Serializable;
import java.util.Objects;

public class Person implements Serializable {

    private static final long serialVersionUID = 1L;

    private Integer id;

    private String name;

    private Integer age;

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

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}';
    }

    @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(id, person.id) &&
                Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }
    
}
String的hashCode( )

String有hash这个实例变量,它的定义如下:

private int hash; // Default to 0

它缓存了hashCode()方法的值,也就是说,第一次调用hashCode()的时候,会把结果保存在hash这个变量中,以后再调用就直接返回保存的值。

我们来看下String类的hashCode方法,代码如下:

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i             
关注
打赏
1660750074
查看更多评论
0.2865s