Set接口中的HashSet与LinkedHashSet

     Set接口也是Collection接口下的一个子接口,它主要包含以下三个实现类:
1:HashSet
2:LinkedHashSet
3:Treeset
     其中,HashSet是Set接口中的主要实现类,下面具体介绍一下Set
1:Set类和List类相反,它所存入的元素的顺序是无序性的并且是不可重复的,也就是说事先存入的时候我们并不能够知道被存入元素将会被放在哪个位置,并且如果尝试存入多个相同的元素,只有第一个能被存进去。
     Set类中的方法是和其父类Collection使用的方法是相同的,具体使用方法请看我的另一篇文章:容器 ;
      下面来看Set主要实现类Hasnset的具体例子
import  java.util.HashSet;
import  java.util.Set;
import  org.junit.Test;
public  class  TestSet {
         @Test
         public  void  TestHashSet1 (){
              Woman  P1  =  new  Woman( "美女"  ,20);
              Woman  P2  =  new  Woman( "美女"  ,20);
               Set  A  =  new  HashSet();
                A .add(123);
                A .add( "帅哥"  );
                A .add( "小孩"  );
               A  .add( "小孩" );
                A .add( P1 );
                A .add( P2 );
              System.  out .println( A  .size());
              System.  out .println( A  );
       }
}
class  Woman{
         private  String  name  ;
         private  int  age  ;
         public  Woman() {
                super ();
       }
         public  Woman(String  name  ,  int  age ) {
                super ();
                this . name  =  name  ;
                this . age  =  age  ;
       }
         @Override
         public  String toString() {
                return  "Woman [name="  +  name  +  ", age="  +  age  +  "]"  ;
       }
}//输出结果如下
// 5
//[小孩, 123, 帅哥, Woman [name=美女, age=20], Woman [name=美女, age=20]]

     通过上面的例子,我们可以看到存入其中的对象的顺序确实是无序的,但是我们发现了一个问题,就是在存入一个对象Woman时,存入两个相同的对象P1与P2居然存了进去,而存入两个 "小孩" 确没有存进去,这是有原因的:
2:由于Set中的元素存入时会使用哈希算法从而达到无序存入元素的目的,当我们在Set中添加对象时,会先调用此对象所在类的hashCode()方法,产生一个哈希值,这个哈希值决定了此对象在Set中被存入的位置,如果在此位置上没有对象存储,则存入这个对象,若已有对象存入,则继续调用equals()方法去比较两个对象是否完全相同,如果相同,则后一个对象时不能够被添加进来的,那么也有以下这几种情况:
     ①两个对象的哈希值相同,但是所含的内容不同
     ②两个对象所含的内容相同,但是算出来的哈希值却是不同的
出现上面情况的原因主要是hashCode()方法中的哈希算法出了问题,也就是说你的哈希算法不够严谨,通常我们 要求在添加进Set中的元素所在的类是必须要重写equals()方法和hashCode()方法的,就像上面那个例子一样,由于Woman类中没有重写这两个方法,所以它调用的equals()和hashCode()方法都是Object类中的(会比较他们的地址想不相同,显然P1与P2的地址是不同的),自然就导致相同的对象都被存了进去,具体的重写方法如下:
         @Override
         public  int  hashCode() {
                final  int  prime  = 31;
                int  result  = 1;
                result  =  prime  *  result  +  age ;
                result  =  prime  *  result  + ((  name  ==  null ) ? 0 :  name  .hashCode());
                return  result  ;
       }
         @Override
         public  boolean  equals(Object  obj ) {
                if  ( this  ==  obj  )
                       return  true  ;
                if  ( obj  ==  null )
                       return  false  ;
                if  (getClass() !=  obj  .getClass())
                       return  false  ;
              Woman  other  = (Woman)  obj ;
                if  ( age  !=  other  . age  )
                       return  false  ;
                if  ( name  ==  null ) {
                       if  ( other  . name  !=  null )
                             return  false  ;
              }  else  if  (! name  .equals( other  . name  ))
                       return  false  ;
                return  true  ;
       }
     所以在今后的开发过程中,在使用到Set类的时候,一定要重写将存入其中的对象所属类中的equals()方法和hashCode()方法。
********************************************************************************************************************************************************
下面来看一个有意思的事情,利用LinkedHashSet实现类去实现Set:
import  java.util.HashSet;
import  java.util.Iterator;
import  java.util.LinkedHashSet;
import  java.util.Set;
import  org.junit.Test;      
                 @ Test
         public  void  TestLinkedHashSet1 (){
               Set  A  =  new  LinkedHashSet();
                A .add(123);
                A .add( "帅哥"  );
                A .add( "小孩"  );
                A .add( "MM"  );
               Iterator  iterator  =  A .iterator();
                while ( iterator  .hasNext())
              {
                     System.  out .println( iterator  .next());
              }
       }
输出结果如下:
123
帅哥
小孩
MM
     细心的朋友可能发现了,这个通过迭代器遍历LinkedHashSet类输出的顺序怎么是按照添加的顺序来的呢,Set类不是说是无序的吗?这里就要说说它的另一个实现类LinkedHashSet了,他使用链表纪录了添加进集合中的顺序,导致我们遍历LinkedHashSet集合的元素时是按照添加的顺序输出的,请看图:


从上图我们可以看到当元素计算完哈希值存入时,指针会按顺序指向下一个插入的结点从而导致了遍历时是按照插入顺序遍历的
     所以,从上面的例子可以显然看出,LiknedHashSet的插入速度要比HashSet慢,但是在迭代访问Set集合中的所有元素时,LinkedHashSet的速度是要优于HashSet的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值