关于Java中的equals()方法与hashCode()方法(二)

2014-11-24 02:50:16 · 作者: · 浏览: 1
y hash functions.
*/
//这是一个增强型的hash
static int hash(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}


public boolean containsKey(Object key) {
  return getEntry(key) != null;
}


final Entry getEntry(Object key) {
//先调用key.hashCod(),再进行了一次增强型hash
int hash = (key == null) 0 : hash(key.hashCode());
for (Entry e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
//先比较hash值,必须相等,再调用两个对象的equals()方法,也必须相等
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
=================================================================================
结论:
(1):可以这样理解哈希(或叫散列),对原始文本进行压缩,产生一个简介(即摘要),并有以下规则:
不同的文本,压缩后,大部分都能得到不同的摘要,但也有少数产生相同的摘要,即产生了碰撞。
相同的文本,压缩后,一定得到相同的摘要。

(2):equals()我们理解成:比较文本是否一样,hashCode()则理解成:比较摘要是否一样。
(3):所以
equals()相同,则hashCode()一定相同。
equals()不相同,hashCode()大部分也不一样,但也有少数产生相同的hashCode(),即产生了碰撞。
(4):所以我们可以这样理解HashMap.get(key)方法
hashCode()是对象的摘要,只不过这个摘要被摘要生成算法限制在[0, table.length - 1]这个闭区间中。
根据key的生成摘要(即数组中的下标),对这个下标上的链表进行循环比较
在摘要相同的前提下(实际上这个链表中的所有元素的摘要都相同,这也正是碰撞的处理方法),
且equals()方法相同(即比较实际上真正关心的内容),则返回正确值。
(5):所以,
如果,equals()相同,而hashCode()不相同,
那么put(key, value)时,原本已存在的key,会被错误的计算出这个key不存在,
所以又在其它位置上存储了一个业务逻辑一样的对象,两个对象之间唯一的区别就是,hash值不一样。
但是get(key)时还是正确的,即取出的还是业务逻辑一样的对象的值。


测试代码如下:

package com.collonn.algorithm.test;

import java.util.HashMap;
import java.util.Random;

class Stu {
	public String name;
	public int age;
	public int hash;

	public Stu() {

	}

	public Stu(String name, int age) {
		this.name = name;
		this.age = age;
		this.hash = new Random().nextInt(9);
	}

	@Override
	public boolean equals(Object obj) {

		if (obj instanceof Stu) {
			Stu stu = (Stu) obj;
			if (stu.name.equals(this.name)) {
				return true;
			} else {
				return false;
			}
		}

		return false;
	}

	public int hashCode() {
		return this.hash;
	}
}

public class Test2 {

	private static void Print(Stu s) {
		System.out.printf("\n name=%s, age=%s, hash=%s", s.name, s.age, s.hash);
	}

	public static void main(String[] args) {
		Stu a = new Stu("a", 1);
		Stu b = new Stu("a", 2);
		Stu c = new Stu("a", 3);

		System.out.printf("\n ------ new ------");
		Print(a);
		Print(b);
		Print(c);

		HashMap
    
      map = new HashMap
     
      (); map.put(a, a); map.put(b, b); map.put(c, c); System.out.printf("\n ------ get ------"); Stu sut = map.get(a); Print(sut); sut = map.get(b); Print(sut); sut = map.get(c); Print(sut); } }