JAVA HashSet equals hashcode

HashSet
(1)特点:
存储顺序与元素添加的顺序无关;
非同步的,如果多个线程要操作HashSet,要通过代码来保持同步。
集合元素值可以是null


(2)HashSet添加元素的过程:
首先调用hashCode()方法来得到该对象的hashCode值,然后根据该hashCode值决定对象在HashSet中的存储位置。
如果该位置上没有元素,则直接存入;
如果该位置上已经保存了元素,调用equals方法,判断这两个元素是否相同。
如果返回true,认为相同,不保存;
如果不相同,保存。此时会在这个存储位置采用链式存储结构,将后来的元素保存在这个位置。

可以看到存储首先判断的是hashCode值,即使两个元素相同(equals),只要他们的hashcode不同,也能被保存进来,显然这是不符合set的定义的。

实际我们比较对象一般使用equals,当equals返回的结果为相等时,认为两个对象相同。此时HashSet的hashCode也应该相等,Treeset使用的comparator的结果也应该为相等。即避免存入相同的元素。因此,将一个对象方法放到HashSet中时,如果重写了equals,也要重写hashcode方法,保证两者的一致性。



import java.util.*;
	class Demo 
	{
		public static void main(String[] args) 
		{
			HashSet h = new HashSet();
			h.add(new Person(1,13));
			h.add(new Person(2,23));
			System.out.println(h.size());
			for(Object temp : h)
			{
				System.out.println(temp.toString());
			}


		}
	}
	class Person
	{
		private int id;
		private int age;
		public Person(int id, int age)
		{
			this.id = id;
			this.age = age;
		}
		public boolean equals(Object obj)
		{
			System.out.println("调用equals判断与本存储位置的已有对象是否相同");
			return false;
		}
		public int hashCode()
		{
			System.out.println("调用hashCode计算Hashcode值,得到存储位置");
			return 1;
		}
	}


结果为:
F:\163netdisk\JAVA学习\java se>java Demo
调用hashCode计算Hashcode值,得到存储位置
调用hashCode计算Hashcode值,得到存储位置
调用equals判断与本存储位置的已有对象是否相同
2
调用hashCode计算Hashcode值,得到存储位置
Person@1
调用hashCode计算Hashcode值,得到存储位置
Person@1
可以看到先调用调用hashCode计算Hashcode值,得到存储位置。第二次存入时,由于hashcode均返回1,即存储位置相同,第二个元素计算得到的存储位置与第一个相同,此时需要判断这两个是否相同。equals均返回false,将两个元素都存储进来。
使用toString()输出hashCode可以看到两个元素的hashCode相同。






(3)hashCode复写的基本规则“


用作equals判断的成员变量都要用来计算hashcode。
equals相等的两个元素hashcode应该也相等。


重写的一般方式如下:
(a)把对象中每个有意义的成员(equals中使用的)计算出一个int行的hashCode值。
不同类型的Field计算HashCode的方式如下
boolean f hashcode=f?0:1;
byte/short/char/int f hashcode=(int)f
long f hashcode=(int)(f^(f>>>32))
float f hashCode=Float.floatToIntBits(f);
double f long lg = Double.doubleToLongBits(f);
hashCode=(int)(lg^(lg>>>32));
普通引用类型 f hashCode=f.hashCode();
(b)将a中计算出来的个Field的值组合计算出一个hashcode值返回。为了避免本来不相等,相加后相等的情况,可以给各Field乘以任意一个质数后再相加。
例如:hashCode=13*f1.hashCode()+17*(int)f2


(4)采用HashCode的优点
相当于以类似于数组的方式给每个元素添加了索引,通过索引可以快速的找到存储位置,得到元素。而不用一个一个的比较元素。HashSet为每个元素通过HashCode方法设置相应的HashCode值,HashCode值对应存储位置。这就是HashSet速度很快的原因。


================================================================

原创文章,转载请注明链接


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值