直接先运行一段代码,看结果:
public class Test {
public static void main(String[] args) {
Map<User, Integer> map = new HashMap<>();
map.put(new User("11"), 11);
map.put(new User("22"), 22);
map.put(new User("33"), 33);
System.out.println(map.get(new User("11")));//此时运行结果为null
}
}
class User {
private String id;
public User(String id) {
this.id = id;
}
// @Override
// public int hashCode() {
// return 31 * id + id.hashCode();
// }
@Override
public boolean equals(Object obj) {
if (obj == null){
return false;
}
if (obj instanceof User) {
obj = (User) obj;
return this.id.equals(((User) obj).getId());
}
return false;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
输出为null,这是为什么,要看map.get()源码:
//方法1
public V get(Object key) {
if (key == null)
return getForNullKey();
Entry<K,V> entry = getEntry(key);
return null == entry ? null : entry.getValue();
}
//方法2
final Entry<K,V> getEntry(Object key) {
if (size == 0) {
return null;
}
int hash = (key == null) ? 0 : hash(key);
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
//方法3
final int hash(Object k) {
int h = hashSeed;
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
h ^= k.hashCode();
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
通过以上源码可以看出get的时候会比较hashCode()的值,再比较equals,所以必须要二者重写。
有些程序可能运行中会存在不稳定的情况,建议从这方便考虑下。曾经有个系统不稳定,给所有实体类重写了这2个方法,问题得以解决。
hashCode()方法重写的一些原则:
a.如果重写equals()方法,检查条件“两个对象通过equals()方法判断相等,那么它们的hashCode()也应该相等”是否成立,如果不成立,则重写hashCode()方法。
b.hashCode()不能太简单,否则容易造成hash冲突;
c.hashCode()不能太复杂,否则会影响性能。
但是一般来说我们不需要自己去写,这里有几种便捷的实现方式:
(1) Google的Guava项目里有处理hashCode()和equals()的工具类com.google.common.base.Objects;
(2) Apache Commons也有类似的工具类EqualsBuilder和HashCodeBuilder;
(3) Java 7 也提供了工具类java.util.Objects;
(4) 常用IDE都提供hashCode()和equals()的代码生成。