Java Collection-HashSet, java-hashset
HashSet Overview
For a HashSet, it is implemented based on HashMap. The underlying layer uses HashMap to store elements. Therefore, if you are familiar with HashMap, it is easy to learn HashSet.
Let's take a look at the simplest constructor of HashSet and several member variables to prove that the underlying layer of HashMap is as follows:
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). */ public HashSet() { map = new HashMap<>(); }
In fact, it is clear in the English comments. First, there is a HashMap member variable. We initialize it in the HashSet constructor. By default, initial capacity is 16 and load factor is 0.75.
Implementation of HashSet
For a HashSet, it is implemented based on HashMap. The HashSet uses HashMap to store all elements at the underlying layer. Therefore, the implementation of HashSet is simple and related HashSet operations, basically, it is done by directly calling the related methods of the underlying HashMap. We should overwrite hashCode () and equals () to the objects stored in the HashSet ()
Constructor
/*** The default parameter-free constructor constructs an empty HashSet. ** An empty HashMap is initialized at the underlying layer, and the default initial capacity is 16 and the load factor is 0.75. */Public HashSet () {map = new HashMap <E, Object> () ;}/ *** constructs a new set containing elements in the specified collection. ** The actual underlying layer uses the default load factor 0.75 and the initial capacity sufficient to contain all elements in the specified collection to create a HashMap. * @ Param c the elements in it will be stored in the collection in this set. */Public HashSet (Collection <? Extends E> c) {map = new HashMap <E, Object> (Math. max (int) (c. size ()/. 75f) + 1, 16); addAll (c) ;}/ *** construct an empty HashSet with the specified initialCapacity and loadFactor. ** The actual underlying layer constructs an empty HashMap with corresponding parameters. * @ Param initialCapacity initial capacity. * @ Param loadFactor: load factor. */Public HashSet (int initialCapacity, float loadFactor) {map = new HashMap <E, Object> (initialCapacity, loadFactor );} /*** construct an empty HashSet with the specified initialCapacity. ** At the underlying layer, an empty HashMap is constructed based on the corresponding parameter and loading Factor loadFactor 0.75. * @ Param initialCapacity initial capacity. */Public HashSet (int initialCapacity) {map = new HashMap <E, Object> (initialCapacity );} /*** construct a new empty link hash set with the specified initialCapacity and loadFactor. This constructor is the package access permission and is not disclosed to the public. * It is actually only support for javashashset. ** At the underlying layer, an empty LinkedHashMap instance is constructed with the specified parameters. * @ Param initialCapacity initial capacity. * @ Param loadFactor: load factor. * @ Param dummy mark. */HashSet (int initialCapacity, float loadFactor, boolean dummy) {map = new LinkedHashMap <E, Object> (initialCapacity, loadFactor );}
Add Method
/*** @ Param e adds the element to this set. * @ Return returns true if the set does not contain the specified element. */Public boolean add (E e) {return map. put (e, PRESENT) = null ;}
If this set does not contain the specified element, add the specified element. More specifically, if this set does not contain meet (e = null? E2 = null: e. equals (e2) element e2, then add the specified Element e to this set. If this set already contains this element, the call does not change the set and returns false. However, the underlying layer actually puts this element as a key into HashMap. Think about why?
When a key-value pair is added to the put () method of HashMap, when the new Entry in HashMap has the same key as the original Entry in the Set (hashCode () returns the same value, returns true through equals comparison). The value of the newly added Entry will overwrite the value of the original Entry.PRESENT
), But the key will not change. Therefore, if an existing element is added to the HashSet, the newly added set element will not be put into the HashMap, the original elements will not change, which satisfies the non-repeated features of the elements in the Set.
If the added element does not exist in the HashSet, true is returned. If the added element already exists, false is returned. The reason is that the put Method about HashMap we mentioned earlier. This method returns null when adding key-value pairs with no duplicate keys.
Other methods
/*** If this set contains the specified element, true is returned. * More specifically, when and only when this set contains a satisfied (o = null? E = null: o. equals (e), returns true. ** The underlying layer actually calls the hashinskey of HashMap to determine whether it contains the specified key. * @ Param o There Is A tested element in this set. * @ Return if this set contains the specified element, true is returned. */Public boolean contains (Object o) {return map. containsKey (o);}/*** if the specified element exists in this set, remove it. More specifically, if this set contains a satisfied (o = null? E = null: o. equals (e) Element e, * remove it. If this set already contains this element, true is returned. ** the underlying layer actually calls the remove Method of HashMap to delete the specified Entry. * @ Param o the object to be removed if it exists in this set. * @ Return if set contains the specified element, true is returned. */Public boolean remove (Object o) {return map. remove (o) = PRESENT;}/*** returns a superficial copy of this HashSet instance: these elements are not copied. ** The underlying layer actually calls the clone () method of HashMap to obtain the superficial copy of HashMap and set it to HashSet. */Public Object clone () {try {HashSet <E> newSet = (HashSet <E>) super. clone (); newSet. map = (HashMap <E, Object>) map. clone (); return newSet;} catch (CloneNotSupportedException e) {throw new InternalError ();}}}