一旦重写了equals方法,就一定要重写hashCode方法。
hashCode方法的约定:
- 一个对象多次调用它的hashCode方法,应当返回相同的integer(哈希值)。
- 两个对象如果通过equals方法判定为相等,那么就应当返回相同integer。相等对象必然导致相等hashCode。
- 两个地址值不相等的对象调用hashCode方法不要求返回不相等的integer,但是要求拥有两个不相等integer的对象必须是不同对象。不相等hashCode必然是不相等对象导致。
在HashMap、HashTable中,put操作是先通过对象的hashCode取模运算后找到存储位置的,如果位置不存在就直接插入,如果存在,就要判定equals方法返回值是否为true,为true说明两个对象字面量是相等的,就覆盖插入。如果为false,说明发生了hash冲突。
重写hashCode方法的目标是:不相等的对象尽可能有不同的hashCode,而且必须满足的一个通用约定是:相等的对象必须具有相同的hashCode。
如果重写了equals方法不去重写hashCode方法,就会导致一种现象:相同的对象有不相等的hashCode,在HashMap机制下就会发生混乱。
重写hashCode方法的示例:
public class HashCodeTest {
private String dishCode;
private boolean weighing;
private String categoryCode;
private boolean currentPrice;
private boolean discountable;
private int stopSell;
private int soldOut;
private boolean deal = false;
private List<DealGroup> dealGroupList;
...
get、set方法
...
@Override
public int hashCode() {
int result = dishCode != null ? dishCode.hashCode() : 0;
result = 31 * result +soldOut;
result = 31 * result +stopSell;
result = 31 * result + (currentPrice ? 1 : 0);
result = 31 * result + (weighing ? 1 : 0);
result = 31 * result + (categoryCode != null ? categoryCode.hashCode() : 0);
result = 31 * result + (dealGroupList != null ? dealGroupList.hashCode() : 0);
return result;
}
}
这里面为啥用个31来计算,而且很多人都是这么写的,这是因为31是个神奇的数字,任何数n*31都可以被jvm优化为(n<<5)-n,移位和减法的操作效率比乘法的操作效率高很多!
31对虚拟机的识别非常友好,对于虚拟机来说31 = 2^5 - 1
网友评论