java-Set-HashSet

特点
实现了Set接口
HashSet依赖的数据结构是HashMap
因为实现的是Set接口,所以不允许有重复的值
插入到HashSet中的对象不保证与插入的顺序保持一致。对象的插入是根据它的hashcode
HashSet中允许有NULL值
HashSet也实现了Searlizable和Cloneable两个接口

初始化尺寸就是当创建哈希表(HashSet内部用哈希表的数据结构)的时候桶(buckets)的数量。如果当前的尺寸已经满了,那么桶的数量会自动增长

装载因子衡量的是在HashSet自动增长之前允许有多满。当哈希表中实体的数量已经超出装载因子与当前容量的积,那么哈希表就会再次进行哈希(也就是内部数据结构重建),这样哈希表大致有两倍桶的数量。

如果内部容量为16,装载因子为0.75,那么当表中有12个元素的时候,桶的数量就会自动增长。

装载因子和初始化容量是影响HashSet操作的两个主要因素。装载因子为0.75的时候可以提供关于时间和空间复杂度方面更有效的性能。如果我们加大这个装载因子,那么内存的上限就会减小(因为它减少了内部重建的操作),但是将影响哈希表中的add与查询的操作。为了减少再哈希操作,我们应该选择一个合适的初始化大小。如果初始化容量大于实体的最大数量除以装载因子,那么就不会有再哈希的动作发生了。

这个类实现了一个哈希表支持的Set接口实现,实际上是一个HashMap
它不能保证集合的迭代顺序,特别不能保证随着时间的推移,秩序将保持不变。
这个类允许null值

此类为基本操作提供恒定的时间性能(add、remove、contains、size).
假设hash函数在桶之间正确地分散元素,在这个集合上迭代需要时间,与HashSet实例大小的和加上HashMap实例支持的capacity(bucket桶的数量)成比例。
因此不设置初始容量太高或者load factor太低是非常重要的 如果迭代性能是重要的,如果迭代性能是重要的。

同步
注意此实现不同步,如果多个线程同时访问哈希集,则至少有一个线程修改集合,它必须外部同步。这通常是通过对某些对象进行同步来实现的。自然封装该集合。

如果不存在这样的对象,则应该使用wrapped {@link Collections#synchronizedSet Collections.synchronizedSet}方法。最好在创建时完成,以防止意外发生。

 Set s = Collections.synchronizedSet(new HashSet(...));

迭代器由class的iterator 是fail-fast 如果这个set可修改的 在任何时候 在迭代器创建之后,如果迭代器在任何时候修改了集合,除了通过迭代器自己的remove方法,
迭代器将会抛出{@link ConcurrentModificationException}.
因此,面对并发修改,iterator 快速而干净失败,而不是在未来时间 不确定的 冒险的行为 。

注意,迭代器的故障快速行为不能得到保证,事实上,一般来说,不可能作出任何硬的保证,存在不同步的并发修改。故障快速迭代器在尽力的基础上抛出ConcurrentModificationException、
*因此,编写一个依赖于此异常正确性的程序是错误的。迭代器的fail-fast行为只用于检测缺陷。


 /** 
     * 如果此set中尚未包含指定元素,则添加指定元素。 
     * 更确切地讲,如果此 set 没有包含满足(e==null ? e2==null : e.equals(e2)) 
     * 的元素e2,则向此set 添加指定的元素e。 
     * 如果此set已包含该元素,则该调用不更改set并返回false。 
     * 
     * 底层实际将将该元素作为key放入HashMap。 
     * 由于HashMap的put()方法添加key-value对时,当新放入HashMap的Entry中key 
     * 与集合中原有Entry的key相同(hashCode()返回值相等,通过equals比较也返回true), 
     * 新添加的Entry的value会将覆盖原来Entry的value,但key不会有任何改变, 
     * 因此如果向HashSet中添加一个已经存在的元素时,新添加的集合元素将不会被放入HashMap中, 
     * 原来的元素也不会有任何改变,这也就满足了Set中元素不重复的特性。 
     * @param e 将添加到此set中的元素。 
     * @return 如果此set尚未包含指定元素,则返回true。 
     */ 
 public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
 // 定义一个虚拟的Object对象作为HashMap的value,将此对象定义为static final。  
    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();

猜你喜欢

转载自blog.csdn.net/qq_16038125/article/details/80888653