hashCode值相关问题

public class Test1 {
    int i = 1;

    @Override
    public int hashCode() {
        return 1;
    }
    public static void main(String[] args) {
        Set set = new HashSet();
        set.add(new Test1());
        set.add(new String("ABC"));
        set.add(new Test1());
        System.out.println(set);
        System.out.println(set.size());
}

老哥们,我重写了hashCode方法 会改变对象底层的哈希码值吗?因为修改后在set中的值就一样了,却没被equals干掉

你要是在set中不重复出现,还得重写equal方法

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7533520
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:List排除、去重与equals和hashCode方法重写
  • 除此之外, 这篇博客: HashSet如何保证存入集合的元素是唯一的?中的 可以见得,hashCode值相等,但元素还是被存储进去了,仅仅重写hashCode()方法是不够的,再重写equals()方法试试 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • package collection;
    
    import java.util.*;
    class Person
    {
        private String name;
        private String address;
        private int age;
        Person(String name,int age,String address){
            this.name = name;
            this.address=address;
            this.age = age;
        }
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + ((address == null) ? 0 : address.hashCode());
    		result = prime * result + age;
    		result = prime * result + ((name == null) ? 0 : name.hashCode());
    		return result;
    	}
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		Person other = (Person) obj;
    		if (address == null) {
    			if (other.address != null)
    				return false;
    		} else if (!address.equals(other.address))
    			return false;
    		if (age != other.age)
    			return false;
    		if (name == null) {
    			if (other.name != null)
    				return false;
    		} else if (!name.equals(other.name))
    			return false;
    		return true;
    	}
    	
    }
    class HashCodeDemo 
    {
        public static void main(String[] args) 
        {
            Set<Person> s = new HashSet<Person>();
            
           
            Person p = new Person("拉格朗日",20,"珠海");
            Person p1 = new Person("拉格朗日",20,"珠海");
            
            System.out.println("p.hashCode=" + p.hashCode());
            System.out.println("p1.hashCode=" + p1.hashCode());
     
            s.add(p);
            s.add(p1);
           
           
            System.out.println(s.size());
        }
    }
    

    输出结果:

    p.hashCode=1690552867
    p1.hashCode=1690552867
    1

  • 以下回答由chatgpt基于相关博客总结生成:

    在Java中,哈希码用于等效性比较和散列表的查找位置。如果两个对象根据equals方法是等效的,则这两个对象必须生成相同的哈希码。因此,当你重写一个类的hashCode方法时,必须确保它不仅仅是使用默认的Object.hashCode()的版本,而且必须采用一个算法,使得哈希码是一个可靠的指示等效性的数值。出于这个原因,建议同时在重写equals方法的同时重写hashCode方法,以确保一致性。一个常见的方式是用对象中的关键域计算哈希码。例如,假设你有一个Person对象,且你想根据其姓名和年龄来比较对象,那么你可以重写它的hashCode方法如下:

    @Override
    public int hashCode() {
        int result = name.hashCode();
        result = 31 * result + age;
        return result;
    }
    

    其中,31是一个不同于其他数的质数,也不是2的幂,具有很好的离散性质。

    然后回答下问题,重写hashCode方法会改变对象的哈希码值,因为默认的hashCode实现是返回对象内存地址的哈希码,而重写hashCode,使用不同的算法来计算哈希码,因此相同hashCode值的对象也会被当作同一个对象。

    如果你的类中有两个对象通过equals方法认为它们是相同的,那么你就需要在这个类中重写hashCode方法,以使得这两个对象有相等的哈希码值。你可以遵循以下三个步骤:

    1. 声明一个int变量result,并将其初始化为对象某个非零常数值。

    2. 对于对象中每个关键域f,完成以下步骤:

    a. 为该域计算int类型的哈希码c。

    b. 合并哈希码:result = 31 * result + c。

    1. 返回result。

    重写hashCode如下:

    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + field1.hashCode();
        result = 31 * result + field2.hashCode();
        ...
        result = 31 * result + fieldN.hashCode();
        return result;
    }
    

    这样就能够使相等的对象拥有相等的哈希码值了。