承接上次的博客 这次要分享的是我在《疯狂java笔记》中对于HashSet类的知识获取
HashSet是set接口的典型实现,大多时候是用的set集合就是HashSet,HashSet按照Hash算法来存储集合中的元素,具有很好的查询和存取性能。
HashSet具有以下特点
不能保证元素的排列顺序,顺序与添加顺序可能不同,并且会很混乱HashSet不是同步的,多线程访问HashSet要保证其同步性几何元素可以为nullHashSet集合判断两个元素相等的标准是两个对象的equals()方法比较性等,而且两个对象的hashCode()方法返回值也相等。
hashSet判断集合元素相等的标准代码块:
//重写A类中equals的方法使其总是返回trueclass A{ @Override public boolean equals(Object obj) { return true; }}//重写B类中的hashcode方法使其总是返回1class B{ @Override public int hashCode() { return 1; }}//重写C类中的equals和hashCode方法使其分别返回true和2class C{ @Override public boolean equals(Object obj) { return true; } @Override public int hashCode() { return 2; }}public class HashSet { public static void main(String[] args) { java.util.HashSet books = new java.util.HashSet(); books.add(new A()); books.add(new A()); books.add(new B()); books.add(new B()); books.add(new C()); books.add(new C()); System.out.PRintln(books); }}**运行结果为: [com.HashSet.B@1, com.HashSet.B@1, com.HashSet.C@2, com.HashSet.A@74a14482, com.HashSet.A@4554617c]**
注:两个A对象的equals()方法比较相等,但是这两个的hashCode值不同,HashSet将其当成两个对象存储在hash表的不同位置,两个B对象的hashCode值虽然相等但是,但由于未重写equals方法,故两个B对象是被HashSet当成两个对象存储在hash标的不同位置,但这时对于Hash表来说是比较麻烦的,Hash表会在同一个用链式结构保存多个对象,如果hashSet中两个以上的元素拥有相同的hashCode,将会导致性能下降。C对象虽然在books集合中添加了两个对象,但由于其equals比较和hashCode比较都相同,故hashSet认为是一个相同的元素,个只能添加一个成功,所以控制台输出的结果只有5个。
hash算法可以根基元素的hashCode值直接计算出元素的存储位置,从而快速定位出该元素。表面看气来HashSet集合中的元素没有索引,实际上由hashCode计算出来的存储位置值可以认定为一个索引,HashSet对比数组来说:数组的长度是固定的,索引是连续的,且不能随意增加数组的长度,但HashSet在这些方面做出的很出色
重写hashCode()方法的基本规则:
程序运行过程中,同一个对象多次调用hashCode()方法应该返回相同的值当两个对象的equals方法比较返回True时,这两个对象的hashCode返回的值应该相等对象中用作equals方法比较标准的实例变量,都应该用于计算hashCode值重写hashCode方法的一般步骤:
把对象内每个有意义的实例变量(即每个参与equals方法比较标准的实例变量)计算出一个int类型的hashCode值计算方式如下:用第一步计算出的hashCode值组合计算出一个hashCode值返回 eg: return f1.hashCode() + (int)f2 注:为了避免直接相加产生偶然相等可以通过为各个实例变量的hashCode值乘以一个质数后在相加。最后请大家注意:当向HashSet中添加可变对象时,必须十分小心。如果修改HashSet中的元素的话与集合中的其他对象相等,从而导致HashSet无法准确访问该对象。
谢谢大家捧场。
新闻热点
疑难解答