关于Java里的hashcode和equal方法

1、这两个方法都是object根类的方法

2、equal在object类里,比较的就是hashcode散列码; 而hashcode方法在object类里,返回的是对象的地址。

但是在常用的JDK里的类中,比如string,都会重写这两个方法,即不同的类会有不同的hashcode计算方法和equal方法(当然在string类里比较的还是hashcode)。

3、当有自定义类时,如果仅仅用来比较两个类,可以只重写equal方法。 

但是,当和容器联系在一起时,比如map、set。要知道,像hashset这种容器,就是把hashmap中的key作为对应存储项的。而且并不是存储对象本身,而是对象的hashcode,存储hash散列码的好处是便于查询。

在java的集合中,判断两个对象是否相等的规则是:
1,判断两个对象的hashCode是否相等
    如果不相等,认为两个对象也不相等,完毕
    如果相等,转入2
2,判断两个对象用equals运算是否相等
    如果不相等,认为两个对象也不相等
    如果相等,认为两个对象相等

综上所述,equal和hashcode两个方法,既独立又有关系。举个例子:

package com.yj.testequal;

public class MyString {
	String mStr;
	int mHashCode;
	
	public MyString(String s, int hashcode) {
		mStr = s;
		mHashCode = hashcode;
	}

	@Override
	public int hashCode() {
		return mHashCode;
	}

	@Override
	public boolean equals(Object obj) {
		if(! (obj instanceof MyString))
			return false;
		return mStr.equals(((MyString)obj).mStr);
	}
	
}


以上自定义类分别重写hashcode和equal。测试一下:

package com.yj.testequal;

import java.util.HashSet;
import java.util.Set;

public class TestEqual {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		MyString m1 = new MyString("fuck1", 123);
		MyString m2 = new MyString("fuck2", 2344);
		
		System.out.println(m1.hashCode());
		System.out.println(m2.hashCode());
		System.out.println(m1.equals(m2));
		
		MyString m3 = new MyString("fuck12", 123);
		System.out.println(m1.equals(m3));
		Set  sms = new HashSet();
		sms.add(m1);
		sms.add(m2);
		
		if(sms.contains(m3)) {
			System.out.println("contains");
		} else {
			System.out.println("not contains");
		}

	}

}

在分别添加了m1和m2后,新建一个对象m3,无论单独让m3的hashcode返回值和m1一样,还是单独让equal返回值一样,在set里都不认为这两个是同一个对象;只有hashcode和equal方法的返回值都相同,才会认为是同一对象。


再说一下为什么集合里要这么比较吧,因为如果集合数量非常大的时候,散列函数会有冲突,就是不同的键可能产生相同的下标;如果hashcode相同的话,就要继续比较equal喽。比较equal方法时就是线性查询了。

注:完美的散列函数在Java SE5的EnumMap和EnumSet中得到了实现。



你可能感兴趣的:(Java)