hashCode方法

hashCode(散列码):

是由对象导出的一个整型值。散列码是没有规律的。

由于hashCode方法定义在Object类中,因此每一个对象都有一个默认的散列码,其值为对象的存储地址。

package com.myself.test;

public class Test {
	public static void main(String[] args) {
		String s = "zhangyaohui";
		StringBuilder ssb = new StringBuilder(s);
		System.out.println(s.hashCode()+"---------"+ssb.hashCode());
		
		String t = "zhangyaohui";
		StringBuilder tsb = new StringBuilder(t);
		System.out.println(t.hashCode()+"---------"+tsb.hashCode());
	}

}
结果:

由上边的结果可以看出,字符串s与拥有相同的散列码,这是因为String类中重写了Object类的hashCode方法,String类的的散列码是由内容导出的,而StringBuilder类中没有定义hashCode方法,它的散列码是由Object类的默认hashCode方法导出的对象的存储地址.

注意:如果重写了equals方法,就必须重新定义hashCode方法,以便用户可以将对象插入到散列表中。

Equals与hashCode的定义必须一致:如果x.equals(y)返回true,那么x.hashCode()就必须与y.hashCode()具有相同的值。


Java对于eqauls方法和hashCode方法是这样规定的:
1、如果两个对象相同,那么它们的hashCode值一定要相同;
2、如果两个对象的hashCode相同,它们并不一定相同
上面说的对象相同指的是用eqauls方法比较。


下面说一下hashCode方法与equals方法之间的联系:


众所周知,Java中的集合有两类,List和Set,List集合内的元素是有序的,元素可以重复,Set集合内的元素是无序的,元素不可以重复。

其实java中的Set集合中的这两个特点就是通过hashCode和equals这两个方法的互相联系来实现的,要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。
于是,Java采用了哈希表的原理。哈希(Hash)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。
这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。


其实这里在java的集合中,判断两个对象是否相等的规则是:
1),判断两个对象的hashCode是否相等
如果不相等,认为两个对象也不相等,完毕
如果相等,转入2)
(这一点只是为了提高存储效率而要求的,其实理论上没有也可以,但如果没有,实际使用时效率会大大降低,所以我们这里将其做为必需的)
2),判断两个对象用equals运算是否相等
如果不相等,认为两个对象也不相等
如果相等,认为两个对象相等(equals()是判断两个对象是否相等的关键)

eg:

package com.myself.test;

import java.util.HashSet;
import java.util.Iterator;

public class Test {
	public static void main(String[] args) {
		
		//String类
		String s1 = new String("zhangyaohui");
		String s2 = new String("zhangyaohui");
		System.out.println(s1.hashCode());
		System.out.println(s2.hashCode());
		System.out.println(s1.equals(s2));
		
		HashSet<String> hs = new HashSet();
		hs.add(s1);
		hs.add(s2);
		Iterator<String> it = hs.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
		
		
		//Student类
		Student st1 = new Student(1, "张耀晖");
		Student st2 = new Student(1, "张耀晖");
		System.out.println(st1.hashCode());
		System.out.println(st2.hashCode());
		System.out.println(st1.equals(st2));
		
		HashSet<Student> hashset = new HashSet();
		hashset.add(st1);
		hashset.add(st2);
		Iterator<Student> itor = hashset.iterator();
		while(itor.hasNext()){
			System.out.println(itor.next());
		}
	}

}

Student类:

package com.myself.test;

public class Student {
	private int num;
	private String name;
	
	public Student(int num,String name){
		this.name = name;
		this.num = num;
	}
	
	
	public String toString() {
		return "学号:"+num+"     姓名: "+name;
	}

}

结果:


版权声明:本文为博主原创文章,未经博主允许不得转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值