中北软院创新实验室

Set集合了解一下

2018-05-24  本文已影响7人  HikariCP

前言

本文使用用的是jdk1.8

Set 接口

我们前面再Collection集合的文章中已经简单的说过Set集合的特点。

需要注意的是:

当可变对象存储到Set集合中的时候,如果通过一种可以影响对象的equals函数的比较结果的方式改变了该对象的话那么Set集合的行为则是不确定的。

Set 集合的常见实现类

image

HashSet

总的来说:

HashSet的属性及函数

image

一眼看上去还是很简单的。只有两个属性,一个是它具体实现类HsahMap,另一个则是一个Object实例。这个Object实例在这里是充当HashMap实例中所有元素的公共value的。因为我们HashSet底层是通过HashMap来实现的,所有元素实际都存储在key中,那么所对应的value如果不赋值则是null值得存在。所以HashSet的处理方式就是将所有元素的value都赋予该Object实例。

所以整个HashSet整体上来说几乎所有的操作都是在底层操作了一个HashMap实例。根据上图我们来看一下HashSet所实现的Set接口的函数都是怎么实现的。

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

public void clear() {
    map.clear();
}

public boolean contains(Object o) {
    return map.containsKey(o);
}

public Iterator<E> iterator() {
    return map.keySet().iterator();
}

public boolean remove(Object o) {
    return map.remove(o)==PRESENT;
}

public int size() {
    return map.size();
}

所有的构造函数所做的也是统一的初始化HashMap的操作

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);
}

HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

TreeSet

总的来说:

TreeSet的属性和函数

image

从图可以很明显的看出它的实现机制和HashSet是一模一样的。底层通过NavigableMap来实现,而NavigableMap则只有TreeMap这一个实现类。我们也可以称之为底层是由TreeMap来实现的,而Object实例则是充当所有元素的value的存在。

image

我们来看一下TreeSet的5个构造函数都是如何实现的

public TreeSet() {
    this(new TreeMap<E,Object>());
}

public TreeSet(Collection<? extends E> c) {
    this();
    addAll(c);
}

public TreeSet(Comparator<? super E> comparator) {
    this(new TreeMap<>(comparator));
}

TreeSet(NavigableMap<E,Object> m) {
    this.m = m;
}

public TreeSet(SortedSet<E> s) {
    this(s.comparator());
    addAll(s);
}

还是清晰的。都是通过构造一个TreeMap来实现整个TreeSet的所有操作的。

LinkedHashSet

总的来说:

LinkedHashSet的属性和函数

image

很纯粹的类,没有自己实现的东西。所有的函数都是继承自各个父类

我们来看一下它的构造函数:

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。

总结

可以看到整个Set集合的实现都是Map映射。

上一篇下一篇

猜你喜欢

热点阅读