美文网首页
hashSet、TreeSet、LinkedHashSet

hashSet、TreeSet、LinkedHashSet

作者: kindol | 来源:发表于2018-05-08 21:00 被阅读0次

    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;
    

    相关文章

      网友评论

          本文标题:hashSet、TreeSet、LinkedHashSet

          本文链接:https://www.haomeiwen.com/subject/ddtgrftx.html