Java-集合第二篇Set集合

Posted zeromz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java-集合第二篇Set集合相关的知识,希望对你有一定的参考价值。

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》

以上是关于Java-集合第二篇Set集合的主要内容,如果未能解决你的问题,请参考以下文章

java中Set集合的遍历方法

怎样从java集合类set中取出数据?

java集合-Set集合

python学习[第十二篇] 数据类型之 集合

Java——Set 集合

第二十七篇 玩转数据结构——集合(Set)与映射(Map)