很多童鞋可能都会有这样的问题, 为什要重写equals和hashCode方法呢? 什么情况下我们会需要重写这些方法呢?
好, 简单的讲, 当我们在使用集合框架, 如: HashSet, HashTable, HashMap的时候, 才有可能用到这些。
为什么说“有可能”呢? 因为并不是所有情况都需要, 废话!
想想我们一般在什么情况下需要用到这些集合框架呢?答案肯定是用来存取数据嘛。
没错, 那我们用什么来取数据呢? 当然一般用key来取啦。
很好, 那我们的key可以是什么类型的呢? - Object
既然是Object, 那么基本类型对应的包装类型和String也应该在这个范畴之内吧。
为什么要把这些包装类和String单独提出来呢? 因为用他们做key的时候就不需要重写equals和hashCode方法。
换言之, 其他的引用类型就都必须实现equals和hashCode方法啦
好啦, 那我们来看个简单的例子:
先往一个HashMap里加入一组Key-Value
然后再去取, 是不是很简单?
public class HashMaps {
public static void main(String[] args) {
Map<Object, Object> testMap = new HashMap<Object, Object>();
Key key1 = new Key("key_name", "key_value");
Key key2 = new Key("key_name", "key_value");
System.out.println("key1 equals key2 ? " + key1.equals(key2));
testMap.put(key1, new Value("value_name", "value_value"));
if (testMap.containsKey(key2)) {
System.out.println(testMap.get(key2));
}
}
static class Key {
private String name;
private String value;
public Key(String name, String value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
static class Value {
private String name;
private String value;
public Value(String name, String value) {
this.name = name;
this.value = value;
}
@Override
public String toString() {
return "Name: " + this.name + " Value: " + this.value;
}
}
}
那么这和我们期望的结果会有什么样的差别呢? 看看执行结果:
引用
key1 equals key2 ? false
好了, 既然这两个对象不“相等”, 那我们就得先让他们相等, 不然怎么可能从HashMap中取出来呢
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Key))
return false;
Key key = (Key) obj;
return key.name.equals(this.name) && key.value.equals(this.value);
}
这样一来, 他们应该就相等了吧。 好再来看看结果:
引用
key1 equals key2 ? true
额~~~ 是相等了, 但是为什还是从HashMap中取不出来呢?
好, 那我们来看看这些所谓的集合框架是如何存取数据的。。。
这样理解好啦:
1. 当我们用put方法把一个对象放到HashMap中的时候, 会根据当前对象的散列码(hashCode)来给它分配一个散列桶(hash bucket)
2. 然后当我们用get方法通过一个对象(key)去取数据的时候, 就会根据你这个key的散列码去查找对应的散列桶, 找到了就返回桶里的值, 找不到则返回null
哦, 原来是两个key的hashCode值不一样啊。。。
那现在该怎样做自然就很明了啦, 重写hashCode方法 (怎样重写?去看看Effective Java吧)
@Override
public int hashCode() {
int result = 17;
result = 31 * result + this.name.hashCode();
result = 31 * result + this.value.hashCode();
return result;
}
看看结果怎样:
引用
key1 equals key2 ? true
Name: value_name Value: value_value
小样, 终于被我取到了吧。。。
水平有限, 就这样啦。。。想砸的砸, 想拍的拍哈。。。欢迎任何意见, 拒绝人身攻击。。。哈哈
分享到:
评论