HashSet story ---- Jdk source code explanation, hashset ---- jdk source code

Source: Internet
Author: User

HashSet story ---- Jdk source code explanation, hashset ---- jdk source code

Hash. When we talk about HashMap, we already know that Hash is a Hash and Map is a ing.

So what is Set?

Let's take a look at the translation of Set.

N. [number] Set; set; [MACHINE] Device

Here, Set indicates a Set. It is also a set of mathematical concepts. What are the characteristics of mathematical concepts? That is, all the elements in the Set cannot be repeated. Therefore, HashSet means to maintain a set of unique elements in the form of hash.

Next, let's take a look at how HashSet is implemented by Jdk. (In fact, the logic is very simple .)

Class declaration:

HashSet inherits from AbstractSet and implements the Set class, clone interface, and serializable interface.

Public class HashSet <E> extends AbstractSet <E> implements Set <E>, Cloneable, java. io. Serializable

An instantaneous hashMap variable is defined in the interface. This variable is the container used by the Set to store elements:

private transient HashMap<E,Object> map;

Next, define an Object variable. Remember the function of this variable: Mark whether the element exists and how to use it. The following describes the method.

private static final Object PRESENT = new Object();

Then there are five constructors:

1. No parameter Constructor

    public HashSet() {        map = new HashMap<>();}

2. During initialization, the elements in the Set can be directly added to the constructor in the Set.

Pay attention to the calculation method of MAP initialization size in this place. The size of the current collection parameter is taken out divided by 0.75 + 1. This value is calculated based on 16 and the value is greater than bytes.

The advantage of doing so is to give map a long enough size, so that when (anti-theft connection: the first self-http://www.cnblogs.com/jilodream/ in this article) map to add elements in the collection, rehash is not required for map. At the same time, if there are few elements in the collection, a suitable size of 16 is still given, leaving enough space for adding elements in the future:

    public HashSet(Collection<? extends E> c) {        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));        addAll(c);    }

3. constructor with initial volume size and loading factor as parameters

    public HashSet(int initialCapacity, float loadFactor) {        map = new HashMap<>(initialCapacity, loadFactor);    }

4. constructor with initial volume size as parameters

    public HashSet(int initialCapacity) {        map = new HashMap<>(initialCapacity);    }

5. Non-public Constructor

The first two parameters of this constructor are the initial volume and loading factor. The third parameter is not used and can be ignored. This is written in the jkd annotation.

At the same time, the map instance used by this constructor is a linkedHashMap, which is different from the constructor on the front.

HashSet(int initialCapacity, float loadFactor, boolean dummy) {        map = new LinkedHashMap<>(initialCapacity, loadFactor);    }

The following is the instance method:
Returns an iterator that essentially returns the key iterator of map in Set.

    public Iterator<E> iterator() {        return map.keySet().iterator();    }

Returns the length of the map in the set as the length of the Set.

    public int size() {        return map.size();}

Determines whether the Set is null. In fact, the returned map length is 0.

    public boolean isEmpty() {        return map.isEmpty();    }

Contains (Object o), the core method of the Set, to determine whether the specified Element o exists in the Set, is essentially to determine whether the key exists in the map

    public boolean contains(Object o) {        return map.containsKey(o);}

Add (E), the core method of Set, add element e to Set.

The essence of this method is to store e as the key and the present variable as the value into the map. The map. put method returns the original value. If it is added for the first time, a null value is returned. (Anti-theft connection: This article first from the http://www.cnblogs.com/jilodream)Therefore, the result returned by add indicates whether the current map already has Element e. If yes, false is returned. Otherwise, true is returned.

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

Remove (Object o), the core method of Set, remove the o element in Set.

If this element exists in the Set, true is returned. Because when the key is removed from the map, the value corresponding to the current key is returned.

    public boolean remove(Object o) {        return map.remove(o)==PRESENT;}

Clear elements in Set

    public void clear() {        map.clear();    }

Clone () method.

Clone the current Set object. The Code shows that only the current Set object and map object are cloned. That is, the addresses of the two are changed, but the specific elements in the map are not cloned.

    @SuppressWarnings("unchecked")    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(e);        }    }

The following two methods are used for positive and negative serialization.

Although this is two private methods, virtual machines can still be called to them through reflection during the deserialization.

First, serialize the writeObject method.

First, call the defaultWriteObject () of the output stream to record the value that can be serialized by the current Set, and then record the volume, load factor, and size of the map. Next, traverse the objects in the map and record the key elements in sequence (the value does not need to be recorded. Why ?).

Deserialization reads data from the stream in reverse order and then generates an object.

Because the stream is read sequentially, the order of deserialization is consistent with that in serialization. We will not introduce the content of forward and reverse serialization too much here. (Anti-theft connection: This article first from the http://www.cnblogs.com/jilodream)

private void writeObject(java.io.ObjectOutputStream s)        throws java.io.IOException {        // Write out any hidden serialization magic        s.defaultWriteObject();        // Write out HashMap capacity and load factor        s.writeInt(map.capacity());        s.writeFloat(map.loadFactor());        // Write out size        s.writeInt(map.size());        // Write out all elements in the proper order.        for (E e : map.keySet())            s.writeObject(e);    } private void readObject(java.io.ObjectInputStream s)        throws java.io.IOException, ClassNotFoundException {        // Read in any hidden serialization magic        s.defaultReadObject();        // Read capacity and verify non-negative.        int capacity = s.readInt();        if (capacity < 0) {            throw new InvalidObjectException("Illegal capacity: " +                                             capacity);        }        // Read load factor and verify positive and non NaN.        float loadFactor = s.readFloat();        if (loadFactor <= 0 || Float.isNaN(loadFactor)) {            throw new InvalidObjectException("Illegal load factor: " +                                             loadFactor);        }        // Read size and verify non-negative.        int size = s.readInt();        if (size < 0) {            throw new InvalidObjectException("Illegal size: " +                                             size);        }        // Set the capacity according to the size and load factor ensuring that        // the HashMap is at least 25% full but clamping to maximum capacity.        capacity = (int) Math.min(size * Math.min(1 / loadFactor, 4.0f),                HashMap.MAXIMUM_CAPACITY);        // Create backing HashMap        map = (((HashSet<?>)this) instanceof LinkedHashSet ?               new LinkedHashMap<E,Object>(capacity, loadFactor) :               new HashMap<E,Object>(capacity, loadFactor));        // Read in all elements in the proper order.        for (int i=0; i<size; i++) {            @SuppressWarnings("unchecked")                E e = (E) s.readObject();            map.put(e, PRESENT);        }    }

The last is the spliterator () method, which is newly added in 1.8.

This method returns a new Spliterator instance corresponding to map. Here we will briefly describe the role of Spliterator: spliterator refers to the meaning of split iterator. That is to say, an iterator is returned, but this iterator is split and elements are divided into several groups, not as the original iterator can only be accessed in a single thread order. It can access elements in the container in the form of multi-thread parallel, accelerating element access efficiency. For detailed use of this class, I will be updated in the subsequent articles (anti-theft connection: This article first from the http://www.cnblogs.com/jilodream.

public Spliterator<E> spliterator() {        return new HashMap.KeySpliterator<E,Object>(map, 0, -1, 0, 0);    }

By viewing the jkd source code, we can find that the essence of HashSet is to encapsulate map. So that the original form of y = f (x) can be better displayed in the form of a mathematical Set.

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.