总述
Set利用Map实现,不允许重复元素(Map中的Key值唯一,可为null)。
- TreeSet,利用TreeMap实现。支持按插入顺序访问,但是添加、删除、包含等操作相对低效(log(n)时间)。
- HashSet,底层是HashMap。利用哈希算法,理想情况,可以提供常数时间的添加、删除、包含等操作,但是不能保证有序。
- LinkedHashSet,用LinkedHashMap实现。内部构建了一个记录插入顺序的双向链表,因此提供了按照插入顺序遍历的能力,同时保证了常数时间的添加、删除、contains等操作,这些操作性能略低于HashSet,因为需要维护链表的开销。
- 遍历元素时,HashSet性能受自身容量影响,初始化时,尽量不要使底层HashMap容量太大。LinkedHashSet由于有双链表,遍历性能只和元素多少有关系。
TreeSet
构造函数:
底层构建了一个TreeMap对象。
public TreeSet() {
this(new TreeMap<E,Object>());
}
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
public TreeSet(Collection<? extends E> c) {
this();
addAll(c);
}
public TreeSet(SortedSet<E> s) {
this(s.comparator());
addAll(s);
}
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
字段:
private transient NavigableMap<E,Object> m;
private static final Object PRESENT = new Object(); // 作为TreeMap的Value
元素操作:
从源码可知,就是在调用TreeMap的操作方法。
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
return m.remove(o)==PRESENT;
}
迭代器:
TreeSet中的TreeMap是按照插入顺序构建的双链表,iterator
方法返回的是TreeMap的KeyIterator迭代器,descendingIterator
方法返回的是TreeMap的DescendingKeyIterator迭代器。所以支持按插入顺序的正向和反向迭代。
public Iterator<E> iterator() {
return m.navigableKeySet().iterator();
}
public Iterator<E> descendingIterator() {
return m.descendingKeySet().iterator();
}
HashSet
构造函数:
public HashSet() {
map = new HashMap<>();
}
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
字段:
private transient HashMap<E,Object> map;
// 仅仅用来充当Map的Value,没有实际意义
private static final Object PRESENT = new Object();
方法举例:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
LinkedHashSet
是HashSet的子类,且没有重写HashSet的方法。
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
public LinkedHashSet() {
super(16, .75f, true);
}
public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}
...
}
从构造方法可知,它们都是调用的HashSet的构造方法,这个构造方法的访问权限是package,使得LinkedHashSet的底层数据结构为LinkedHashMap。
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
上一篇:JDK1.8并发之生产者消费者问题
下一篇:无