java覆盖equals()方法时总要覆盖hashCode()

我们再用JAVA创建自己的类的时候,一种比较常见的覆盖就是覆盖Object中的equals()方法和hashCode()方法。如果不这样做的话,就很可能违反Object.hashCode()的通用约定,从而在利用自己建的类构建需要Hash化的集合的正常工作。其中有一条约定很重要:

如果两个对象利用equals方法比较是相等的,那么这两个对象必须能返回同样的hashCode。

这一点很好理解,就比如拿Set来说,Set的特点就是元素是无须的且不可重复。那么这里面所谓的重复的定义,就是需要程序员通过equals去定义的,既然你覆盖了equals()方法,那么也就是你已经定义了重复的概念。那么如果equals()返回了True就意味着hashCode()必须返回一样的散列码。


举个栗子,我这里新建了三个类:

1.User:没有覆盖equals也没有覆盖hashCode

package com.blog.hash;

public class User {
	private int id;
	private String name;
	public User(int id, String name) {
		// TODO Auto-generated constructor stub
		this.id = id;
		this.name = name;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
}
2.EqualUser:只覆盖equals方法

package com.blog.hash;

public class EqualUser {
	private int id;
	private String name;

	public EqualUser(int id, String name) {
		// TODO Auto-generated constructor stub
		this.id = id;
		this.name = name;
	}

	public int getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		EqualUser other = (EqualUser) obj;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

}
3.HashUser:覆盖了equals和hashCode方法

package com.blog.hash;

public class HashUser {
	private int id;
	private String name;
	public HashUser(int id, String name) {
		// TODO Auto-generated constructor stub
		this.id = id;
		this.name = name;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		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;
		HashUser other = (HashUser) obj;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
	
}
除此之外还写了一个测试类MyTest

package com.blog.hash;

import java.util.HashSet;
import java.util.Set;

import org.junit.Test;

public class MyTest {
	@Test
	public void withoutOveride() {
		User u1 = new User(1, "mike");
		User u2 = new User(1, "mike");
		Set<User> set = new HashSet();
		set.add(u1);
		set.add(u2);
		System.out.println(u1.equals(u2));
		for (User u : set) {
			System.out.println(u.getId() + u.getName());
		}
	}

	@Test
	public void withAllOveride() {
		HashUser u1 = new HashUser(1, "mike");
		HashUser u2 = new HashUser(1, "mike");
		Set<HashUser> set = new HashSet();
		set.add(u1);
		set.add(u2);
		System.out.println(u1.equals(u2));
		for (HashUser u : set) {
			System.out.println(u.getId() + u.getName());
		}
	}

	@Test
	public void withEqualOveride() {
		EqualUser u1 = new EqualUser(1, "mike");
		EqualUser u2 = new EqualUser(1, "mike");
		Set<EqualUser> set = new HashSet();
		set.add(u1);
		set.add(u2);
		System.out.println(u1.equals(u2));
		for (EqualUser u : set) {
			System.out.println(u.getId() + u.getName());
		}
	}

}
在方法withoutOveride中,新建了两个User对象,因为User没有覆盖equals也没有覆盖hashCode,所以调用的是Object的方法。因此equals比较的是引用,所以equals()返回false,打印结果为:

false
1mike
1mike

这里u1和u2明显是同一个值,只是引用不一样,所以在实际使用的时候会覆盖equals方法。


在方法withEqualOveride中,建立两个EqualUser对象,由于覆盖了equals方法而没有覆盖hashCode,所以调用equals时返回true,而hashCode还是Object的方法,打印结果为:
true
1mike
1mike
这样在set中就存在了重复的值,所以会导致在使用hash话的集合的时候出现问题。

最后,在方法withAllOveride中,由于覆盖了equals和hashCode方法,因此调用equals方法的时候返回的是true,同时set中没有重复的值,打印结果为:

true
1mike

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值