hashSet、TreeSet、LinkedHashSet

2018-05-08  本文已影响0人  kindol

HashSet

内部是hashMap或者LinkedHashMap(当为LinkedHashSet的时候)实现,看构造函数就知道

然而,问题来了,map是<key, value>,而set是只有key的,那么传入的value是什么,看看add方法

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

传入了一个PRESENT,礼物?,在源码开头可以看到定义如下

private static final Object PRESENT = new Object();

而且,这里是static final变量,也就是说永远只有一个,利用了缓存原理,所以不会占用value的空间;这里的HashSet又给包装了一下,如果key没有重(oldValue==null),就返回true,否则返回false。(remove方法也有判断)

其余的方法都是调用hashmap做简单封装

TreeSet

HashSet是以HashMap为基础的,那么TreeSet当然也就以TreeMap为基础了,然而,发现其底层是一个NavigableMap接口类型的,这个接口实现了SortedMap,而TreeMap实现了NavigableMap这个接口,兜了一个圈子,发现

NavigableMap m = new TreeMap<>();

方法的包装跟HashSet差不多,操作Set里面的元素其实就是操作Map里面的元素

TreeSet是有序的,但并不是按照元素添加的顺序,而是按照里面的内容顺序

LinkedHashSet

这个更厉害了,以HashSet进行继承,进一步封装,底层是LinkedHashMap

LinkedHashMap的每一个键值对都是通过内部的静态类Entry<K, V>实例化的。这个Entry<K,V>类继承了HashMap.Entry类。这个静态类增加了两个成员变量
before和after来维护LinkedHasMap元素的插入顺序。这两个成员变量分别指向前一个和后一个元素,这让LinkedHashMap也有类似双向链表的表现

private static class Entry<K,V> extends HashMap.Entry<K,V>
{
    // These fields comprise the doubly linked list used for iteration.
    Entry<K,V> before, after;

    Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
        super(hash, key, value, next);
    }
}

而链表肯定不能缺少头结点,所以LinkedHashMap还定义了头结点

private transient Entry<K,V> header;
上一篇下一篇

猜你喜欢

热点阅读