`
huhu_long
  • 浏览: 73552 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

About equals & hashCode

阅读更多
很多童鞋可能都会有这样的问题, 为什要重写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


小样, 终于被我取到了吧。。。

水平有限, 就这样啦。。。想砸的砸, 想拍的拍哈。。。欢迎任何意见, 拒绝人身攻击。。。哈哈
分享到:
评论
1 楼 zhang_he 2011-08-18  
so good
Global site tag (gtag.js) - Google Analytics