标签:不同的 bit 排列 添加 ret 向量 利用 整数 枚举
1、Set集合与Collection基本相同,没有提供额外的方法。实际上Set就是Collection,只是行为略有所不同(Set不允许有重复元素)。
Set下的HashSet、TreeSet、EnumSet完全使用于上面Set的有关规则(即元素不能够重复)。
2、HashSet
(1)HashSet按Hash算法来存储集合中的元素,因此具有良好的存取和查找性能。
HashSet具有的特点:
1》不能保证元素的排列顺序。
2》HashSet不是同步的,即不是线程安全的。
3》集合元素值可以为null。
(2)当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该hashCode值决定该对象在HashSet中的存储位置。
HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等。
1》如果有两个元素通过equals()方法比较返回true,但它们的hashCode()方法返回值不相等,HashSet就认为它们是不同的元素,依然可以添加到HashSet中,它们将存储在不同的位置。(注:public boolean equals(Object o)、public int hashCode()方法均来自Object)
所以,当某种类型需要放到HashSet中,并且需要重写其equals()方法,则相应的hashCode()方法也应该重写。规则是:如果两个对象通过equals()方法比较返回返回true,这两个对象的hashCode值也应该相同。
2》如果两个元素比较equals()方法返回true,hashCode()返回不同的值,这与Set集合的规则冲突;equals()返回false,hashCode()返回相同的值,HashSet将试图把它们保存在同一个位置,但又不行,这时候在这个位置使用链式结构来保存多个对象。
HashSet访问元素是根据元素的hashCode值来快速定位的,如果HashSet中存在两个以上的元素具有相同的hashCode值(上面使用链式结构保存),将会导致性能下降。
3》HashSet中每个能存储元素的“槽位”(slot)通常也称为“桶”(bucket),如果多个元素equals()返回false,hashCode()返回相同hashCode(链式结构存储),就需要在“桶”中放多个元素,从而导致性能下降。重写hashCode()方法的基本规则:
1>同一个对象调用多次hashCode()方法应该返回相同的值。
2>当equals()方法返回true时,hashCode()应该返回相同的hashCode值。
3>对象中用作equals()方法比较标准的实例变量,都应该用于计算hashCode值。
(3)重写hashCode()方法的一般步骤
1》把对象内每个有意义的实例变量(即每个参与equals()方法比较标准的实例变量)计算出一个int类型的hashCode值。计算方式举例:
实例变量类型 | 计算方式 |
boolean | hashCode=(f?0:1); |
float | hashCode=Float.floatToIntBits(f); |
double |
long l=Double.doubleToLongBits(f); hashCode=(int)(l^(1>>>32)); |
long | hashCode=(int)(f^(f>>>32)); |
整数类型(byte、short、char、int) | hashCode=(int)f; |
引用类型 | hashCode=f.hashCode(); |
2》利用第一步计算得到的多个hashCode值组合计算出一个hashCode值返回,如直接相加作为最终的hashCode值返回。
3》为了避免直接相加产生的偶然相等,可以通过为各实例变量的hashCode值乘以任意一个质数后再相加。
return f1.hashCode()*17+(int)f2*29;
(4)如果向HashSet中添加了一个可变对象后,后面程序修改了该可变对象的实例变量值,则可能导致它与集合中的其他元素相同(equals()返回true,hashCode()也返回相同的值),从而可能导致HashSet中包含两个相同的对象。这是一个值得注意的问题。
3、LinkedHashSet
也是通过元素的hashCode值决定元素的存储位置,但它同时使用链表维护元素的次序,遍历LinkedHashSet中的元素时,LinkedHashSet将会按照元素添加顺序来访问集合中的元素。
LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet的性能,但在迭代访问集合中的全部元素时将有很好的性能。
4、TreeSet
5、EnumSet
专门为枚举类设计的集合类。EnumSet中的所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式或隐式地指定。EnumSet的集合元素也是有序的,EnumSet以枚举值在Enum类内的定义顺序来决定集合元素的顺序。
EnumSet在内部以位向量的形式存储,这种存储形式非常紧凑、高效,因此EnumSet对象占用内存很小,而且运行效率很好。
EnumSet集合不允许加入null元素,否则将抛出空指针异常。
EnumSet类没有暴露任何构造器来创建该类的实例,但它提供了类方法创建对象。提供创建EnumSet对象的方法有:
1》
标签:不同的 bit 排列 添加 ret 向量 利用 整数 枚举
原文地址:https://www.cnblogs.com/ZeroMZ/p/11380504.html