3.9 在覆盖equals()后,总是覆盖hashCode()

Set,Map等类会首先调用对象的hashCode(),根据返回的hash值比较对象是否相同(一般情况下可提高性能)。如果两个对象返回的hash值相同,则再调用对象的equals()进行比较。

 

以下类覆盖了equals(),使用phoneNumber比较对象是否相同:

package com.bingo.practice.effective.three.nine;

public class PhoneNumber {
	private int phoneNumber;
	
	public PhoneNumber(int phoneNumber){
		this.phoneNumber=phoneNumber;
	}
	
	public int getPhoneNumber(){
		return this.phoneNumber;
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj==this)return true;
		if(!(obj instanceof PhoneNumber))return false;
		
		PhoneNumber target=(PhoneNumber)obj;
		return this.phoneNumber==target.getPhoneNumber();
	}
	
}

 

以下测试将失败,尽管phoneNumber1和phoneNumber2是相同的(phoneNumber属性值都是123),但是由于未覆盖hashCode(),两者返回的hash值是不同的。当使用phoneNumber2作为key从hashmap里获取值时,hashmap判断自身不包含phoneNumber2返回的hash值,因此直接返回null。

	@Test
	public void testHashCode(){
		PhoneNumber phoneNumber1=new PhoneNumber(123);
		PhoneNumber phoneNumber2=new PhoneNumber(123);
		
		Map<PhoneNumber, String> container=new HashMap<PhoneNumber, String>();
		container.put(phoneNumber1, "bingo");
		
		Assert.assertEquals(container.get(phoneNumber2), "bingo");
	}

 

PhoneNumber覆盖hashCode()后,以上测试将通过,代码如下:

	@Override
	public int hashCode() {
		return phoneNumber;
	}

 

 

 

覆盖hashCode的基本原则:

1.如果两个对象使用equals()比较是相同的,那么hashCode()必须返回相同的值

 

2.如果两个对象是不同的,hashCode()可以返回相同的值。但是建议返回不同的值以提高性能

 

需要注意的地方:

1.Object的hashCode()一般返回对象的内存地址作为hash值,但是也可能对两个不同的对象返回相同的hash值(与JVM的实现有关)

 

2.推荐使用Apache Commons的HashCodeBuilder覆盖hashCode()

 

 

 

 

 

 

你可能感兴趣的:(hashCode())