Java:equals和hashCode的懂得

Java:equals和hashCode的理解

    我们一般使用equals都是为了比较对象的内容,而Object里面的equals方法却是比较对象的引用,如下:

public boolean equals(Object obj) {
        return (this == obj);
    }
所以当我们想要比较的是对象的内容时,需要重写equals方法,假设User类中有String name , int age 两个字段,用eclipse自动生成的equals方法写法如下:

public boolean equals(Object obj) {
	if (this == obj)
		return true; // 两者引用相等则是同一个对象故内容相等
	if (obj == null)
		return false;
	if (getClass() != obj.getClass())  // 两者的类不相等,则内容不可能相等
		return false;
	User other = (User) obj;  // 将其向下转型
	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;
}
一个测试用例

public class Test {
	public static void main(String[] args) {
		User user1 = new User();
		User user2 = new User();
		System.out.println(user1.equals(user2));
 	}
}
打印true。如果把User类重写的equals方法去掉,此时user1.equals()调用的是Object类的equals方法,比较的是引用而不是内容,user1和user2的引用明显不同,故打印false。常用的equals方法比较的是对象的内容,即对象要属于同一个类且字段属性相等才相等。

    HashCode主要用于类集框架。假设我们对一个类不重写hashCode方法,对象调用hashCode方法时则调用的是Object类的hashCode方法:

public native int hashCode();
生成的散列值都是不相同的,而如果我们重写了hashCode方法,对于内容相同的对象则可以生成相同的散列值

至于hashCode方法写法,我们一般也不需要记住,直接用工具生成就好了。

测试用例:

public class Test {
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		HashSet<User> set = new HashSet<>();
		User user1 = new User("leelit", 21);
		User user2 = new User("leelit", 21);
		User user3 = new User();
		
		System.out.println(user1.hashCode());
		System.out.println(user2.hashCode());
		System.out.println(user3.hashCode());
		
		set.add(user1); // 添加user1和user2
		set.add(user2);
		System.out.println(set.size());

		HashMap<User, String> map = new HashMap<>();
		map.put(new User("lina", 21), "value");
		System.out.println(map.get(new User("lina", 21)));
	}
}

打印结果:

-1106625705
-1106625705
961
1
value

把User类重写的hashCode方法去掉后打印:

31168322
17225372
5433634
2
null

没有重写hashCode方法时:两个对象即使内容相等,也生成不同的散列值,所以都可以add进set里面去,我们知道HashSet是不可以有重复的元素的,所以这就是为什么必须要重写hashCode的原因;同理对于HashMap虽然put和get的是同样的key,但由于散列值不同,而被视作了不同的key,所以无法取出来。

重写hashCode方法后,两个相等的对象会生成相同的散列值。