集合-HashSet

参考博客:https://www.cnblogs.com/runwulingsheng/p/5208762.html

                  https://www.cnblogs.com/ysocean/p/6555373.html

Set<E> hashset = new HashSet<>();

 

1.概述: HashSet不能保证元素的顺序(非线性结构的集合);不允许重复元素;非线程安全;集合元素可以为NULL

 

2.意义:其底层其实是一个数组,存在的意义是加快查询速度。我们知道在一般的数组中,元素在数组中的索引位置是随机的,元素的取值和元素的位置之间不存在确定的关系,因此,在数组中查找特定的值时,需要把查找值和一系列的元素进行比较,此时的查询效率依赖于查找过程中比较的次数,而在链表中查询更是需要耗费大量时间。而 HashSet 集合底层数组的索引和值有一个确定的关系:index=hash(value),那么只需要调用这个公式,就能快速的找到元素或者索引。

 

3.具体实现

1、当向HashSet集合中存入一个元素时,HashSet会先调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据hashCode值决定该对象在HashSet中的存储位置
      1.1、如果 hashCode 值不同,直接把该元素存储到 hashCode() 指定的位置
      1.2、如果 hashCode 值相同,那么会继续判断该元素和集合对象的 equals() 作比较
          1.2.1、hashCode 相同,equals 为 true,则视为同一个对象,不保存在 hashSet()中
          1.2.2、hashCode 相同,equals 为 false,则存储在之前对象同槽位的链表上,这非常麻烦,我们应该约束这种情况,即保证:如果两个对象通过 equals() 方法返回 true,这两个对象的 hashCode 值也应该相同。
注意:每一个存储到 哈希 表中的对象,都得提供 hashCode() 和 equals() 方法的实现,用来判断是否是同一个对象
   对于 HashSet 集合,我们要保证如果两个对象通过 equals() 方法返回 true,这两个对象的 hashCode 值也应该相同。
 
public class SetTest {


    public void Hashrun(){
        HashSet<Integer> hashset = new HashSet<>();

        hashset.add(33);
        hashset.add(3);
        hashset.add(333);
        hashset.add(3323);
        hashset.add(33413);
        hashset.add(3353);
        hashset.add(31353);
        hashset.add(13353);

        Iterator<Integer> it = hashset.iterator();

        while(it.hasNext()){
            System.out.println(it.next());
        }
    }

    public static void main(String[] args){
        SetTest st = new SetTest();
        st.Hashrun();
    }
}

输出结果为:

33
3
33413
3353
31353
13353
3323
333

 

4.特点

     4.1   HashSet的add()方法,是根据每个数据的散列码和当前HashSet的大小决定位置的,如在添加某个数据前,获取到其散列码为51564,然后当前的HashSet散列单元为128个,则该数据可能会被存储在51564%128=108个链表中。

     4.2    为什么HashSet查找效率提高了?

知道了HashSet的add机制后,查找的道理一样。直接根据数据的散列码和散列表的数组大小计算除余后,就得到了所在数组的位置,然后再查找链表中是否有这个数据即可。

   查找的代价也就是在链表中,但是真正一条链表中的数据很少,有的甚至没有。几乎没有什么迭代的代价可言了。所以散列表的查找效率建立在散列单元所指向的链表中的数据要少 。

posted @ 2019-03-18 14:26  胡叁安  阅读(195)  评论(0编辑  收藏  举报