Java Container Set Interface

Source: Internet
Author: User

The Set interface allows you to conveniently Save the specified type in a variable as a Set type. Set is a Collection that does not contain repeated elements. More specifically, Set does not contain any element pair that meets e1.equals (e2), and contains at most one null element. The underlying storage implementation of the Set interface depends on the implementation of Map. It can be said that the management of elements in the Set interface is the management of keys in the Map. The following describes the implementation classes of various Set interfaces, including HashSet, LinkedHashSet, and TreeSet.

 

1. HashSet

HashSet is implemented by HashMap at the underlying layer. It stores key-value pairs such as [key-Object constants], and also includes initialCapacity and loadFactor. These two parameters have the same meaning as HashMap, is important. In addition, the elements in the HashSet set are unordered.

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).     */    public HashSet() {    map = new HashMap<E,Object>();    }    /**     * 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<E,Object>(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<E,Object>(initialCapacity, loadFactor);    }

 

2. LinkedHashSet

LinkedHashSet inherits the HashSet, but its underlying storage uses LinkedHashMap, so the elements in it are inserted in sequence. I can see that the javashashset class only defines four constructor methods and does not see the content related to the linked list. Why does the javashashset internally use the linked list to maintain the element insertion sequence (insertion sequence? Click here to see the construction method HashSet (int initialCapacity, float loadFactor, boolean dummy) of the three parameters. Then we will find that the implementation class used is 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.     *     * @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, 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<E,Object>(initialCapacity, loadFactor);    }

 

3. TreeSet

The underlying storage of TreeSet uses TreeMap, which can extract ordered sequences from the Set. The elements must implement the Comparable interface. Otherwise, they are sorted by default dictionary.

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.  All elements inserted into     * the set must implement the {@link Comparable} interface.     * Furthermore, all such elements must be <i>mutually     * comparable</i>: {@code e1.compareTo(e2)} must not throw a     * {@code ClassCastException} for any elements {@code e1} and     * {@code e2} in the set.  If the user attempts to add an element     * to the set that violates this constraint (for example, the user     * attempts to add a string element to a set whose elements are     * integers), the {@code add} call will throw a     * {@code ClassCastException}.     */    public TreeSet() {    this(new TreeMap<E,Object>());    }

Summary:

HashSet is a Set designed for fast search. The elements stored in HashSet must define hashCode (). HashSet has the query speed of HashSet and maintains the element sequence (insertion sequence) using the linked list internally ), when you use the iterator to traverse the Set, the result is displayed in the insert order. The elements must define the hashCode () method. The TreeSet stores the Set in order, and the underlying layer is the tree structure, it can be used to extract ordered sequences from the Set, and the elements must implement the Comparable interface.

In addition, here we will mention the significance of hashcode and equals in Set. When performing a set operation with hash as the underlying layer, the system first searches for the corresponding linked list using hashcode, then traverses the corresponding linked list using equals to compare the key, and finally finds the corresponding value. As mentioned last time, when the hashcode method is poorly designed, the element distribution may be uneven. Then, a large number of equals are called to compare keys, which affects the program execution efficiency.

    public V put(K key, V value) {        if (key == null)            return putForNullKey(value);        int hash = hash(key.hashCode());        int i = indexFor(hash, table.length);        for (Entry<K,V> e = table[i]; e != null; e = e.next) {            Object k;            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {                V oldValue = e.value;                e.value = value;                e.recordAccess(this);                return oldValue;            }        }        modCount++;        addEntry(hash, key, value, i);        return null;    }

Finally, I would like to raise a frequently asked question during the interview: When the hashcode of the two objects is equal, their equals do not necessarily return true; however, when equals of two objects return true, their hashcode must be the same.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.