Java重写ToString()、equals和hashCode区别

0. "==" 和 equals区别

Object类中的equals方法和“==”是一样的,没有区别,即俩个对象的比较是比较他们的栈内存中存储的内存地址。而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==不同”,他们比较的是值是不是相等

//“==”对于基本数据类型,判断两个变量的值是否相等。/“equal”不能用于基本数据类型

1、为什么要重写ToString?

所有的对象都会有这个方法【继承Object】,如下默认情况下:getName+@+hashCode的16进制

    //java.lang.Object

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

 正常情况下:我们需要将对象按照字符串的方式输出出来,也就是说,需要知道这个对象的各个变量的值。所以需要进行toString()重写

@Data 注解会生成如下的结果

public String toString() {
    return "Person(name=" + getName() + ", age=" + getAge() + ")";
}

Person

@Data
@AllArgsConstructor
public class Person {
    String name;
    Integer age;
}

Solution

public class Solution {
    public static void main(String[] args) {
        Person person = new Person("luoyu", 12);
        System.out.println(person);
        System.out.println(JSON.toJSONString(person));

        String s = "{\"age\":12,\"name\":\"luoyu\"}";
        Person parseObject = JSON.parseObject(s, new TypeReference<Person>() {
        });

        System.out.println(parseObject.getAge());
    }
}

 输出结果

Person(name=luoyu, age=12)
{"age":12,"name":"luoyu"}
12

//特殊说明:使用JSON可以直接对对象进行序列化和反序列化 

 2. Java中的Collection有两类,一类是List,一类是Set

equals和HashCode深入理解以及Hash算法原理_K_天道酬勤-CSDN博客_hashcode算法原理

List内的元素是有次序的,元素可以重复。Set元素无序,但元素不可重复 

Set里面的判断重复,使用了Hash原理

当Set接收一个元素时根据该对象的内存地址算出hashCode,看它属于哪一个区间,再这个区间里调用equeals方法。【特别注意】这里需要注意的是:当俩个对象的hashCode值相同的时候,Hashset会将对象保存在同一个位置,但是他们equals返回false,所以实际上这个位置采用链式结构来保存多个对象。
这里写图片描述

 

 

package com.luoyu.json;

/**
 * @author :luoyu
 * @version :1.0
 * @date : 2022/2/26 1:53 上午
 * @description
 */

public class RectObject {
    public int x;
    public int y;
    public RectObject(int x,int y){
        this.x = x;
        this.y = y;
    }
    @Override
    public int hashCode(){
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }
    @Override
    public boolean equals(Object obj){
        if(this == obj)
            return true;
        if(obj == null)
            return false;
        if(getClass() != obj.getClass())
            return false;
        final RectObject other = (RectObject)obj;
        if(x != other.x){
            return false;
        }
        if(y != other.y){
            return false;
        }
        return true;
    }
}
package com.luoyu.json;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * @author :luoyu
 * @version :1.0
 * @date : 2022/2/25 4:51 下午
 * @description
 */

public class Main {
    public static void main(String[] args) {
        HashSet<RectObject> set = new HashSet<RectObject>();
        RectObject r1 = new RectObject(3,3);
        RectObject r2 = new RectObject(5,5);
        RectObject r3 = new RectObject(3,3);
        set.add(r1);
        set.add(r2);
        set.add(r3);
        set.add(r1);
        System.out.println("size:"+set.size());
    }
}

我们向HashSet中存入到了四个对象,打印set集合的大小,结果是多少呢? 运行结果:size:2
为什么会是2呢?这个很简单了吧,因为我们重写了RectObject类的hashCode方法,只要RectObject对象的x,y属性值相等那么他的hashCode值也是相等的,所以先比较hashCode的值,r1和r2对象的x,y属性值不等,所以他们的hashCode不相同的,所以r2对象可以放进去,但是r3对象的x,y属性值和r1对象的属性值相同的,所以hashCode是相等的,这时候在比较r1和r3的equals方法,因为他么两的x,y值是相等的,所以r1,r3对象是相等的,所以r3不能放进去了,同样最后再添加一个r1也是没有没有添加进去的,所以set集合中只有一个r1和r2这两个对象

下面我们把RectObject对象中的hashCode方法注释,即不重写Object对象中的hashCode方法,在运行一下代码:
运行结果:size:3
这个结果也是很简单的,首先判断r1对象和r2对象的hashCode,因为Object中的hashCode方法返回的是对象本地内存地址的换算结果,不同的实例对象的hashCode是不相同的,同样因为r3和r1的hashCode也是不相等的,但是r1==r1的,所以最后set集合中只有r1,r2,r3这三个对象,所以大小是3
 

下面我们把RectObject对象中的equals方法中的内容注释,直接返回false,不注释hashCode方法,运行一下代码:
运行结果:size:3 这个结果就有点意外了,我们来分析一下:
首先r1和r2的对象比较hashCode,不相等,所以r2放进set中,再来看一下r3,比较r1和r3的hashCode方法,是相等的,然后比较他们两的equals方法,因为equals方法始终返回false,所以r1和r3也是不相等的。 r1和r1的hashCode以及Equals都是相同的。所以是3.

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
重写equalshashCode方法,需要在类中重写这两个方法。以下是一个示例代码,其中假设有一个名为Person的类,其中包含age和name属性。 ``` import java.util.Objects; public class Person { private int age; private String 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 age == person.age && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(age, name); } // 比较年龄升序,年龄相同时比较英文姓名升序 public int compareTo(Person otherPerson) { int result = Integer.compare(this.age, otherPerson.age); if (result == 0) { result = this.name.compareTo(otherPerson.name); } return result; } // toString方法 @Override public String toString() { return "Person{" + "age=" + age + ", name='" + name + '\'' + '}'; } } ``` 在equals方法中,我们比较了两个Person对象的age和name属性是否相等。在hashCode方法中,我们使用了Objects类的hash方法来生成hashCode。对于比较年龄和英文姓名,我们在类中添加了一个compareTo方法,其中比较了两个Person对象的age和name属性,如果当前对象的age小于otherPerson对象的age,则返回-1,如果当前对象的age大于otherPerson对象的age,则返回1,如果当前对象的age等于otherPerson对象的age,则比较name属性。最后,我们在类中添加了toString方法,用于将Person对象转换为字符串输出。 示例代码中,可以通过以下方式将Person对象按照年龄升序,年龄相同时按照英文姓名升序排列: ``` List<Person> personList = new ArrayList<>(); personList.add(new Person(25, "Tom")); personList.add(new Person(18, "Bob")); personList.add(new Person(18, "Adam")); Collections.sort(personList); System.out.println(personList); ``` 输出: ``` [Person{age=18, name='Adam'}, Person{age=18, name='Bob'}, Person{age=25, name='Tom'}] ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值