HashSet:
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* the specified initial capacity and default load factor (0.75).
*
* @param initialCapacity the initial capacity of the hash table
* @throws IllegalArgumentException if the initial capacity is less
* than zero
*/
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。底层数据结构其实是HashMap,固定value,将数据存入key中,利用HashMap的key不可重复的特点实现该集合特性。
特点:
不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也可能发生变化; HashSet不是同步的; 集合元素值可以是null;
内部存储机制:当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode方法来得到该对象的hashCode值,然后根据该hashCode值决定该对象在HashSet中的存储位置。如果有两个元素通过equals方法比较true,但它们的hashCode方法返回的值不相等,HashSet将会把它们存储在不同位置,依然可以添加成功。也就是说。HashSet集合判断两个元素的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode方法返回值也相等。靠元素重写hashCode方法和equals方法来判断两个元素是否相等,如果相等则不添加,依此来确保元素的唯一性由于其是使用hashmap中的key实现的,所以其逻辑就是hashmap的key定位逻辑,数组加链表形式,一定长度后,链表转成二叉树。
hash表:容量:hash表中桶的数量;初始化容量:创建hash表时桶的数量;尺寸:当前hash表中记录的数量;负载因子:负载因子等于0表示空的hash表,0.5表示半满的hash表,轻负载的hash表具有冲突少、适宜插入与查询等特点。负载极限:负载极限是一个0~1之间的数值,决定了hash表的最大填满程度。当hash表的负载因子达到指定负载极限时,hash表会自动成倍地增加容量,并将原有的对象重新分配,放入新的桶中。HashSet、HashMap、Hashtable默认的负载极限是0.75。
LinkedHashSet:
/**
* Constructs a new, empty linked hash set. (This package private
* constructor is only used by LinkedHashSet.) The backing
* HashMap instance is a LinkedHashMap with the specified initial
* capacity and the specified load factor.
*
* @param initialCapacity the initial capacity of the hash map
* @param loadFactor the load factor of the hash map
* @param dummy ignored (distinguishes this
* constructor from other int, float constructor.)
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
LinkedHashSet继承于HashSet,但是由于在HashSet的初始化代码处做了处理,如果是HashSet,则内部的数据是HashMap实现,如果是LinkedHashSet,则内部数据使用的是LinkedHashMap,LinkedHashSet集合也是根据元素的hashCode值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,即数组加双向链表的组合,这样就能从头节点按插入顺序迭代整个数据链。这样使得元素看起来是以插入的顺序保存的,也就是说当遍历集合LinkedHashSet集合里的元素时,集合将会按元素的添加顺序来访问集合里的元素。输出集合里的元素时,元素顺序总是与添加顺序一致。但是LinkedHashSet依然是HashSet,因此它不允许集合重复。
TreeSet:
TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态(不是添加顺序,而是根据数据进行排序)。
内部存储机制TreeSet内部实现的是 红黑树,默认整形排序为从小到大。TreeSet支持两种排序方法:自然排序和定制排序,在默认情况下,采用的是自然排序。自然排序:TreeSet会调用集合元素的compareTo(Objec obj)方法来比较元素之间的大小关系,然后将集合元素按升序排列,这就是自然排序。定制排序:Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现该接口的类必须实现该方法,实现了该接口的类必须实现该方法,实现接口的类就可以比较大小了。当调用一个一个对象调用该方法与另一个对象进行比较时,如果返回0表示两个对象相等;如果返回正整数则表明obj1大于obj2,如果是负整数则相反。
CopyOnWriteArraySet:
线程安全,底层使用的是CopyOnWriteArrayList,使用其特性实现的线程安全效果和不重复的效果,CopyOnWriteArrayList本身就有一个如果不存在才允许添加的api可以使用 addIfAbsent。
ConcurrentSkipListSet:
线程安全,其内部使用ConcurrentSkipListMap作为数据的存储,依旧使用其key。