HashSet類(lèi)定義
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable{}
主要是繼承了AbstractSet,實(shí)現(xiàn)了Set接口旅薄。
主要成員變量
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
我們知道set是一個(gè)無(wú)重復(fù)元素的集合瘟判,那么元素到底是如何保存呢蕉扮?實(shí)質(zhì)是保存在一個(gè)HashMap里整胃,這里使用的是map的key來(lái)保存元素,而map里面所有的value都是下方的PRESENT這個(gè)對(duì)象喳钟。
主要構(gòu)造方法
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();
}
/**
* Constructs a new set containing the elements in the specified
* collection. The <tt>HashMap</tt> is created with default load factor
* (0.75) and an initial capacity sufficient to contain the elements in
* the specified collection.
*
* @param c the collection whose elements are to be placed into this set
* @throws NullPointerException if the specified collection is null
*/
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* 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
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
/**
* 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的構(gòu)造方法比較靈活屁使,第一個(gè)是最簡(jiǎn)單的構(gòu)造方法;第二個(gè)是使用一個(gè)Collection來(lái)初始化map奔则,注意方法里調(diào)整了HashMap的初始容量蛮寂;第三個(gè)是根據(jù)參數(shù)設(shè)定初始大小和loadFactor;第四種就是指定了初始大小易茬。
主要方法
/**
* Adds the specified element to this set if it is not already present.
* More formally, adds the specified element <tt>e</tt> to this set if
* this set contains no element <tt>e2</tt> such that
* <tt>(e==null ? e2==null : e.equals(e2))</tt>.
* If this set already contains the element, the call leaves the set
* unchanged and returns <tt>false</tt>.
*
* @param e element to be added to this set
* @return <tt>true</tt> if this set did not already contain the specified
* element
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
添加元素方法很簡(jiǎn)單,map.put(e, PRESENT)==null;
酬蹋,如果之前存在e了及老,那么返回false,如果不存在,返回true
/**
* Removes the specified element from this set if it is present.
* More formally, removes an element <tt>e</tt> such that
* <tt>(o==null ? e==null : o.equals(e))</tt>,
* if this set contains such an element. Returns <tt>true</tt> if
* this set contained the element (or equivalently, if this set
* changed as a result of the call). (This set will not contain the
* element once the call returns.)
*
* @param o object to be removed from this set, if present
* @return <tt>true</tt> if the set contained the specified element
*/
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
刪除元素方法也很簡(jiǎn)單范抓,使用map.remove(o)
即可骄恶。
public boolean contains(Object o) {
return map.containsKey(o);
}
查詢(xún)是否存在該元素。
public boolean isEmpty() {
return map.isEmpty();
}
HashSet是否為空
/**
* Returns an iterator over the elements in this set. The elements
* are returned in no particular order.
*
* @return an Iterator over the elements in this set
* @see ConcurrentModificationException
*/
public Iterator<E> iterator() {
return map.keySet().iterator();
}
返回iterator匕垫。
注意的地方
HashSet就是使用HashMap實(shí)現(xiàn)的僧鲁,HashMap不是線程安全的,HashSet同樣也不是線程安全的象泵,接下來(lái)需要分析HashMap這個(gè)類(lèi)寞秃。
LinkedHashSet類(lèi)定義
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
}
可以看到,LinkedHashSet繼承了HashSet偶惠,我們知道春寿,LinkedHashSet是保持插入順序的一種Set,那么是如何保證呢忽孽?請(qǐng)看構(gòu)造方法绑改。
主要構(gòu)造方法
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
/**
* Constructs a new, empty linked hash set with the specified initial
* capacity and the default load factor (0.75).
*
* @param initialCapacity the initial capacity of the LinkedHashSet
* @throws IllegalArgumentException if the initial capacity is less
* than zero
*/
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
/**
* Constructs a new, empty linked hash set with the default initial
* capacity (16) and load factor (0.75).
*/
public LinkedHashSet() {
super(16, .75f, true);
}
/**
* Constructs a new linked hash set with the same elements as the
* specified collection. The linked hash set is created with an initial
* capacity sufficient to hold the elements in the specified collection
* and the default load factor (0.75).
*
* @param c the collection whose elements are to be placed into
* this set
* @throws NullPointerException if the specified collection is null
*/
public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}
可以看到,構(gòu)造方法均是調(diào)用了父類(lèi)方法扒腕,具體是哪個(gè)父類(lèi)方法呢绢淀?
/**
* 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);
}
這個(gè)構(gòu)造方法的說(shuō)明里提到了,此方法僅提供給LinkedHashSet瘾腰,里面是用LinkedHashMap來(lái)代替了HashMap。
HashSet和LinkedHashSet背后都是map覆履,所以需要研究下map系列蹋盆。