AbstractCollection中的方法已经在《java数据结构与并发之--List(基础篇)》里已经做过了介绍,已经实现了Collection接口方法,而Set接口本身没有特殊的方法需要继承,在AbstractSet中只重写了 hashCode 和 equals 方法,另外根据Set本身的特征对removeAll方法进行重写来可能性的提高性能。同时值得注意的是,AbstractSet中并没有iterator()的方法进行实现,也没有扩展出特殊的iterator方法。
HashSet 和 LinkedHashSet 是我们经常会用到的常用的Set的实现类。我们先看一下HashSet,打开HashSet源码你会第一眼看到的就是 这样两个实例变量:
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
AbstractSet,这个在具体讲解到 Map 数据结构时再详细讲解),只有以下构造方法:
/**
* 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<E,Object>(initialCapacity, loadFactor);
}
/**
* 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<E,Object>(initialCapacity, loadFactor);
}
HashSet的内容就是这些,我们来看一下LinkedHashSet:(没有任何的特殊方法,只利用了我们上面说道的调用 LinkedHashMap 的特殊构造方法修改重写所有的HashSet构造方法,让所有的方法都走了 LinkedHashMap的实现。)
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
private static final long serialVersionUID = -2851667679971038690L;
/**
* Constructs a new, empty linked hash set with the specified initial
* capacity and load factor.
*
* @param initialCapacity the initial capacity of the linked hash set
* @param loadFactor the load factor of the linked hash set
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
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);
}
}
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
private static final long serialVersionUID = -2851667679971038690L;
/**
* Constructs a new, empty linked hash set with the specified initial
* capacity and load factor.
*
* @param initialCapacity the initial capacity of the linked hash set
* @param loadFactor the load factor of the linked hash set
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
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);
}
}
List中同理 EmptySet 是实现一个空的Set, 然后 SynchronizedSet 实现一个同步级的 Set,UnmodifiableSet针对修改的方法实现抛出异常来实现了不允许修改的含义。
AbstractSet的子类提供的方法几乎没有对Collection接口进行特别的添加,同时java提供了另外一种Set接口: public interface SortedSet<E> extends Set<E>,我们可以看出这种接口继承至Set同时根据类名的意思就是可排序的Set接口,同时它新提供了以下接口方法:
Method Summary | |
|
Returns the comparator used to order the elements in this set, or null if this set uses the natural orderingof its elements. |
|
Returns the first (lowest) element currently in this set. |
|
Returns a view of the portion of this set whose elements are strictly less than toElement. |
|
Returns the last (highest) element currently in this set. |
|
Returns a view of the portion of this set whose elements range from fromElement, inclusive, to toElement, exclusive. |
|
Returns a view of the portion of this set whose elements are greater than or equal to fromElement. |
SortedSet,java1.6又对SortedSet接口进行了扩展出了NavigableSet接口,TreeSet增加了NavigableSet接口的实现,其中NavigableSet接口多出了以下方法:
Method Summary | |
|
Returns the least element in this set greater than or equal to the given element, or |
|
Returns an iterator over the elements in this set, in descending order. |
|
Returns a reverse order view of the elements contained in this set. |
|
Returns the greatest element in this set less than or equal to the given element, or |
|
Returns a view of the portion of this set whose elements are less than (or equal to, if |
|
Returns the least element in this set strictly greater than the given element, or |
|
Returns the greatest element in this set strictly less than the given element, or |
|
Retrieves and removes the first (lowest) element, or returns |
|
Retrieves and removes the last (highest) element, or returns |
|
Returns a view of the portion of this set whose elements range from |
|
Returns a view of the portion of this set whose elements range from fromElement, inclusive, to toElement, exclusive. |
|
Returns a view of the portion of this set whose elements are greater than (or equal to, if |
接口中多出了更多的和顺序性相关的接口,包括倒序(descending*),临界的(ceiling,floor,higher,lower)最大值,最小值,另外提供了pollFirst, pollLast方法进行取出并删除首尾,同时对headSet,tailSet进行增强,这两个新方法提供了是否包含equals本元素。
CopyOnWriteArraySet内部的数据结构,所有的方法都是通过调用 al 来实现的。具有Set特性的方法,通过CopyOnWriteArrayList提供的 addAllAbsent, addIfAbsent, remove等方法来实现其功能。可以看到CopyOnWriteArraySet 只是使用了 CopyOnWriteArrayList里的几个特有方法实现了Set的功能,其基本的内部原理都还和CopyOnWriteArrayList一样。
ConcurrentNavigableMap相应的方法实现。
CopyOnWriteArraySet 使用了之前分析过的 CopyOnWriteArrayList做为内部数据结构进行实现的。分析Set的并发情况,其基本并发情况跟在说List中的情况基本一致,HashSet , LinkedHashSet, TreeSet 线程非安全,不适合多线程下被多个线程使用,多线程下的Set考虑使用 Collections.SynchronizedSet ,CopyOnWriteArraySet ,其中CopyOnWriteArraySet 读操作频繁,写操作较少的情况下性能较高。Collections.UnmodifiableSet 用于在确定不让此数据结构不能修改的情况下使用,基本理论和List并发情况的论述中是一致的。