什么是hashCode方法,该方法的含义是什么?
- hashCode值的不唯一性
- 类若没有重写hashCode(),默认使用 Object的hashCode()方法生成散列码,Object默认是使用对象的地址计算散列码。
- 下面的示例, 由于散列码不同,所以map中没有找到key,此时应该重写 hashCode(), 但是重写 hashCode()还不够, 同时也必须重写equals() 方法,因为不同对象的hashCode有可能是相同的hashCode值,同时也说明了hashCode值的不唯一性
- 重写equals() 方法,当hashCode的值一样时,就会使用equals()判断当前的“键”是否与链表中的存在的键“相同”
- 特性1: 如果两个对象心相同,则 他们的hashCode值一定相等
- 特性2: 如果两个对象的hash值相同, 则两个对象不一定相同。
- 特性3:如果两个对象的hash值不相同,则两个对象一定不相同。
应该如何重写HashCode()
- lombok EqualsAndHashCode,工具已经帮我们重写了hashCode
- 生成速度必须快 并且必须有意义,也就是说必须使用对象来生成散列码
- 应该产生分布均匀的散列码,如果散列码都集中到一个区域,那么该区域的负载会比较严重
public class TestHashCodeA {
private Integer age;
public TestHashCodeA(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "TestHashCodeA{" +
"age=" + age +
'}';
}
}
@Slf4j
public class TestHashCodeB {
public static void main(String[] args) {
Map<TestHashCodeA, Integer> map = new HashMap<>(16);
TestHashCodeA ta4 = null;
for (int i = 0; i < 5; i++) {
ta4 = new TestHashCodeA(i);
map.put(ta4,i);
}
log.info("map is {}", JSONObject.toJSONString(map));
TestHashCodeA ta = new TestHashCodeA(4);
// (new TestHashCodeA(4)).hashCode() !=(new TestHashCodeA(4)).hashCode()
// 由于散列码不同,所以map中没有找到key
log.info("ta hashCode is {} VS ta4 hashCode is {}", ta.hashCode(),ta4.hashCode());
Integer integer = map.get(ta);
log.info("map.get(ta) value is {}", integer);
Integer integer4 = map.get(ta4);
log.info("map.get(ta4) value is {}", integer4);
}
}
// -----------------------输出结果 ---------------------
18:00:26.423 [main] INFO demo.p0809.TestHashCodeB - map is {{}:0,{}:2,{}:1,{}:4,{}:3}
18:00:26.429 [main] INFO demo.p0809.TestHashCodeB - ta hashCode is 1316864772 VS ta4 hashCode is 403716510
18:00:26.429 [main] INFO demo.p0809.TestHashCodeB - map.get(ta) value is null
18:00:26.429 [main] INFO demo.p0809.TestHashCodeB - map.get(ta4) value is 4
什么是equals方法,该方法的含义是什么?
重写equals应该满足以下特性:
- 自反性, x.equals(x)
- 对称性: a.equals(b) ==> b.equals(a)
- 传递性: a.equals(b);b.equals© ==> a.equals©
- 一致性: 无论调用x.equal(y)多少次,结果不变
- 对任何非null的x,x.equals(null)一定返回false。