zoukankan      html  css  js  c++  java
  • 源码分析之Set

    HashSet源码分析

       底层是HashMap

    public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable
    {
        static final long serialVersionUID = -5024744406713321676L;
    
        private transient HashMap<E,Object> map;
        // Dummy value to associate with an Object in the backing Map
        private static final Object PRESENT = new Object();
    
        /**
         * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has default initial capacity (16) and load factor (0.75).
         * 使用HashMap的默认容量大小16和默认加载因子0.75初始化map,构造一个HashSet.
       */ public HashSet() { map = new HashMap<>(); } /** * Constructs a new set containing the elements in the specified collection. The <tt>HashMap</tt> is created with default load factor * (0.75) and an initial capacity sufficient to contain the elements in the specified collection. * * @param c the collection whose elements are to be placed into this set * @throws NullPointerException if the specified collection is null */ public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); } /** * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has 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 * @throws IllegalArgumentException if the initial capacity is less than zero, or if the load factor is nonpositive */ public HashSet(int initialCapacity, float loadFactor) { map = new HashMap<>(initialCapacity, loadFactor); } /** * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has the specified initial capacity and default load factor (0.75). * * @param initialCapacity the initial capacity of the hash table * @throws IllegalArgumentException if the initial capacity is less than zero */ public HashSet(int initialCapacity) { map = new HashMap<>(initialCapacity); } /** * 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<>(initialCapacity, loadFactor); } }

    EnumSet源码分析

      底层是Enum.

    public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, java.io.Serializable
    {
        /**
         * The class of all the elements of this set.
         */
        final Class<E> elementType;
    
        /**
         * All of the values comprising T.  (Cached for performance.)
         */
        final Enum<?>[] universe;
    
        private static Enum<?>[] ZERO_LENGTH_ENUM_ARRAY = new Enum<?>[0];
    
        EnumSet(Class<E>elementType, Enum<?>[] universe) {
            this.elementType = elementType;
            this.universe    = universe;
        }
    }

    TreeSet源码分析

      底层是TreeMap,而TreeMap底层数据结构是红黑树。

    public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable
    {
        /**
         * The backing map.
         */
        private transient NavigableMap<E,Object> m;
        // Dummy value to associate with an Object in the backing Map
        private static final Object PRESENT = new Object();
        /**
         * Constructs a set backed by the specified navigable map.
         */
        TreeSet(NavigableMap<E,Object> m) {
            this.m = m;
        }
    
        /**
         * Constructs a new, empty tree set, sorted according to the  natural ordering of its elements.  */
        public TreeSet() {
            this(new TreeMap<E,Object>());
        }
    
        /**
         * Constructs a new, empty tree set, sorted according to the specified comparator.  
         * @param comparator the comparator that will be used to order this set.
         *        If {@code null}, the {@linkplain Comparable natural ordering} of the elements will be used.
         */
        public TreeSet(Comparator<? super E> comparator) {
            this(new TreeMap<>(comparator));
        }
    
        /**
         * Constructs a new tree set containing the elements in the specified collection, sorted according to the <i>natural ordering</i> of its elements. 
         * @param c collection whose elements will comprise the new set
         * @throws ClassCastException if the elements in {@code c} are
         *         not {@link Comparable}, or are not mutually comparable
         * @throws NullPointerException if the specified collection is null
         */
        public TreeSet(Collection<? extends E> c) {
            this();
            addAll(c);
        }
    
        /**
         * Constructs a new tree set containing the same elements and using the same ordering as the specified sorted set.
         * @param s sorted set whose elements will comprise the new set
         * @throws NullPointerException if the specified sorted set is null
         */
        public TreeSet(SortedSet<E> s) {
            this(s.comparator());
            addAll(s);
        }
    }

    LinkedHashSet源码分析

      底层是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.
         * 构造方法继承自HashSet中生成的的LinkedHashMap
         * @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);
        }
    
        
        @Override
        public Spliterator<E> spliterator() {
            return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
        }
    }

    总结

       1、Set 的内部实现其实是一个 Map,即HashSet的内部实现是一个HashMap,TreeSet的内部实现是一个TreeMap,LinkedHashSet的内部实现是一个LinkedHashMap。

          2、允许Null值,且只有一个。

       3、但是 Set 中只有一个元素,又是怎么变成(key,value)的呢? 以 HashSet 的 add 方法为例:

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

         原来是,把添加到 Set 中的元素作为内部实现 map 的 key,然后用一个常量对象 PRESENT 对象,作为value。所有的 HashSet 共用同一个PRESENT对象,所有的 TreeSet 共用同一个 PRESENT对象,所有的 LinkedHashSet 共用同一个 PRESENT 对象。这是因为 Set 的元素不可重复和 Map 的 key 不可重复有相同特点。Map 有一个方法 keySet() 可以返回所有 key。

  • 相关阅读:
    使用PHP Socket 编程模拟Http post和get请求
    php socket客户端及服务器端应用实例
    php五大运行模式CGI,FAST-CGI,CLI,ISAPI,APACHE模式浅谈
    php 连接 mssql sql2008
    开源内容管理系统Joomla正式发布3.5版本 基于PHP 7
    swift--使用 is 和 as 操作符来实现类型检查和转换 / AnyObject与Any的区别
    swift--获取window
    ios开发之--ios11适配:TableView的heightForHeaderInSection设置高度无效/UISearchBar消失
    swift--触摸(UITouch)事件(点击,移动,抬起)
    swift--添加新手引导页
  • 原文地址:https://www.cnblogs.com/ryjJava/p/14318363.html
Copyright © 2011-2022 走看看