Java Note-hashmap

Source: Internet
Author: User
Tags concurrentmodificationexception

HashMap uses the data structure, the jargon "list hash", the code is real

    /**     * 定义了一个Entry的数组用来存储数据。     */     transient Entry[] table;
' Java/** * Entry is an internally defined class */Static class Entry<k,v> implements Map.entry<k,v> {/** * Defines two constants key, that is hashmap key * Value,key corresponding value * Next, the next entry object, so entry data structure is a single item of the linked list * Constant hash value, it can be said that he is a bucket,      Stored is actually the subscript value of the table array.        */FINAL K key;        V value;        Entry<k,v> Next;        final int hash;         /** * Construction method.            */Entry (int h, K K, v V, entry<k,v> N) {value = V;            Next = n;            key = k;        hash = h;        } Public final K GetKey () {return key;        Public final V GetValue () {return value;            /** value is set to return old values */public final V SetValue (v newvalue) {v oldValue = value;            value = newvalue;        return oldValue; The public final Boolean equals (Object o) {if (!) (            o instanceof Map.entry)) return false; Map.entrY e = (map.entry) o;            Object K1 = GetKey ();            Object K2 = E.getkey (); if (k1 = = K2 | | (K1! = null && k1.equals (K2)))                {Object V1 = GetValue ();                Object v2 = E.getvalue (); if (v1 = = V2 | |                    (V1! = null && v1.equals (v2)))            return true;        } return false; } public final int hashcode () {return (key==null? 0:key.hashcode ()) ^ (Value==nu ll?        0:value.hashcode ());        Public final String toString () {return GetKey () + "=" + GetValue ();        The/** * will call it when the HashMap put method is called, but it's itself an empty method, and the current understanding is that Linkedhashmap will override this method, * each time you put the object at the end of the doubly linked list,        * Because Linkehashmap to implement the LRU algorithm, I will specifically write Linkedhashmap, * to explain can go there to see. */void Recordaccess (hashmap<k,v> m) {}/** * This method is invoked whenever the ENTR   Y is * removed from the table.      */void Recordremoval (hashmap<k,v> m) {}} 
    • Transient is implemented in a class that is serializable, and is ignored when attributes that are identified by transient are serialized.
        if (loadfactor <= 0 | | Float.isnan (Loadfactor)) throw new IllegalArgumentException ("Illegal load factor:" + loadfactor);  
      Returning true means that the incoming loadfactor is NaN = 0.0f/0.0f;
       /**hashmap The place where the data is stored, the length is always 2 recurses (because there is a ' and ' action on the length of the bucket, the other function follows), the default initial 16*/transient entry[] table;  
      The maximum data that is allowed to be stored in the
       /**table table can actually be calculated (Table.size () *loadfactor+1) but is used in many applications and is more convenient with constant representation. */final float loadfactor;  
      The
       /** load factor means that the data can store a percentage relative to the total capacity, default 0.75, and when the data exceeds Loadfactor (Table.size () *loadfactor+1), resize () is called, Increase the table capacity, re-hash to locate all data, cost performance, so for the dataset can be predicted in advance data size, you can set this value when initialized and the initial capacity initialcapacity*/final float Loadfactor;  
       /** When the HASHMAP structure changes (removing data or adding data), the value is modified, modcount++, and the main function is HashMap is non-thread safe, Each time the iterator is called to determine whether Modcount is modified during this period, it will throw concurrentmodificationexception, a security mechanism if it changes the description data. */transient int modcount;  
    /**    hashMap本身是散列表结构,它定位元素的逻辑是先取key的hashcode,再通过此hash函数    再次hash,之后调用indexFor()根据table表的长度取余,找到存储的偏移量,之后再比较value的值。    此次hash的目的是因为key的hashcode无法保证高质量的将元素散列开来。    NULL的key,将定位到0    */    static int hash(int h) {        h ^= (h >>> 20) ^ (h >>> 12);        return h ^ (h >>> 7) ^ (h >>> 4);    }
```java/**get方法,其实没啥好说的,时间复杂度因为散列数据结构故O(1)*/  public V get(Object key) {        if (key == null)            return getForNullKey();        int hash = hash(key.hashCode());        for (Entry<K,V> e = table[indexFor(hash, table.length)];             e != null;             e = e.next) {            Object k;            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))                return e.value;        }        return null;    }
 /** This is also quite simple, the main next recordaccess (this), entry in the method, in the HashMap, there is no operation, put this method and Recordremoval, is reserved for other classes such as Linkedhashmap: used to implement the LRU permutation algorithm. It is interesting to look at Linkedhashmapaddentry (hash, key, value, I) to add value to the list of keys.        */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; }
 /** Create a new entry, head interpolation method.         Mainly in the resize () method */void AddEntry (int hash, K key, V value, int bucketindex) {entry<k,v> e = Table[bucketindex];        Table[bucketindex] = new entry<> (hash, key, value, E);    if (size++ >= threshold) Resize (2 * table.length); }
/** when the size stored in the HashMap is not less than threshold (capacity * load factor), you need to resize the table, reorder the elements each time you resize it, and it will be a time-consuming operation when the amount of data is large. And we should try to make our initial hashmap capacity close to the capacity/loadfactor to be used and reduce the number of replacements.        */void Resize (int newcapacity) {entry[] oldtable = table;        int oldcapacity = Oldtable.length;            if (oldcapacity = = maximum_capacity) {threshold = Integer.max_value;        Return        } entry[] newtable = new Entry[newcapacity];        Transfer (newtable);        Table = newtable;    threshold = (int) (newcapacity * loadfactor);     /** * Re-hash the data in the old table into the new table.        */void Transfer (entry[] newtable) {entry[] src = table;        int newcapacity = Newtable.length;            for (int j = 0; J < Src.length; J + +) {entry<k,v> e = src[j];                if (E! = null) {SRC[J] = null;                    do {entry<k,v> next = E.next;                    int i = indexfor (E.hash, newcapacity); E.next = NewtaBle[i];                    Newtable[i] = e;                e = next;            } while (E! = null); }        }    }
  ' Java/** remove operation */public V Remove (Object key) {entry<k,v> E = Removeentryforkey (        Key);    return (E = = null? null:e.value);        } final entry<k,v> Removeentryforkey (Object key) {int hash = (key = = null)? 0:hash (Key.hashcode ());        int i = indexfor (hash, table.length);        Entry<k,v> prev = table[i];        entry<k,v> e = prev;            while (E! = null) {entry<k,v> next = E.next;            Object K; if (E.hash = = Hash && (k = e.key) = = Key | | (Key! = null && key.equals (k))))                {modcount++;                size--;                if (prev = = e) Table[i] = next;                else Prev.next = next;                E.recordremoval (this);            return e;            } prev = e;        e = next;    } return E; }
The 
  "' Java/**hashmap contains the corresponding value, and a ContainsKey method does not say, want to mention this is because, the judgment contains value need to loop, time complexity O (n). Use cautiously.        */public boolean containsvalue (Object value) {if (value = = null) return Containsnullvalue ();        entry[] tab = table; for (int i = 0, i < tab.length; i++) for (Entry e = tab[i]; E! = null; e = E.next) if (val        Ue.equals (E.value)) return true;    return false; }
"' java/** finally is the hashmap iteration, together, hashiterator internal private class, a few properties in the Expectedmodcount above the HashMap add delete operation, will update a modcount, the beginning has been said , is HashMap is non-thread-safe, this property is used during iteration to determine whether the value of HashMap has been updated during the iteration, and Expectedmodcount is judged during the iterative process of iterateor construction. So, when we use iterators to traverse HashMap, if we want to modify the HashMap content at the same time (only delete).  Use the Remove method provided by Iterator */private Abstract class Hashiterator<e> implements iterator<e> {entry<k,v>        Next   Next entry to return int expectedmodcount;              for Fast-fail int index;     Current slots entry<k,v> current;            Current Entry Hashiterator () {expectedmodcount = Modcount;                if (Size > 0) {//advance to first entry entry[] t = table;                Navigates to a location that is not NULL in the first value.            while (Index < t.length && (next = t[index++]) = = null);        }} public Final Boolean hasnext () {return next! = NULL; } final entry<k,v> NextEntry () {            During the iteration, the element is modified to throw concurrentmodificationexception if (modcount! = expectedmodcount) th            Row new Concurrentmodificationexception ();            Entry<k,v> e = next;            if (E = = null) throw new Nosuchelementexception ();                if (next = e.next) = = null) {entry[] t = table;            while (Index < t.length && (next = t[index++]) = = null);            } current = e;        return e;            } public void Remove () {if (current = = null) throw new IllegalStateException ();            if (modcount! = expectedmodcount) throw new Concurrentmodificationexception ();            Object k = Current.key;            current = null;            HashMap.this.removeEntryForKey (k);        Expectedmodcount = Modcount; }}/** three private iterators, which means we can iterate hashmap in these three ways. */Private Final class Valueiterator extends Hashiterator<V> {public V next () {return nextentry (). value; }} Private Final class Keyiterator extends hashiterator<k> {public K next () {return nexte        Ntry (). GetKey (); }} Private Final class Entryiterator extends hashiterator<map.entry<k,v>> {public map.entry<        K,v> Next () {return nextentry ();   }}//Subclass overrides these to alter behavior of views ' iterator () method iterator<k> Newkeyiterator ()    {return new keyiterator ();    } iterator<v> Newvalueiterator () {return new valueiterator ();    } iterator<map.entry<k,v>> Newentryiterator () {return new entryiterator (); }/** OK, three sides of the three kinds of iterative initialization, can only provide internal use of the package, the actual exposure of the method is the following three, but the original, you judge to see for themselves.    The corresponding iterator can be called according to their own needs the initial assignment of these three types is keyset,values and EntrySet respectively.        */Public set<k> KeySet () {set<k> KS = KeySet; return (KS! = null? KS: (KeYset = new KeySet ())); } Private Final class KeySet extends abstractset<k> {public iterator<k> Iterator () {RET        Urn Newkeyiterator ();        } public int size () {return size;        Public Boolean contains (Object o) {return containskey (o);        The public boolean remove (Object o) {return HashMap.this.removeEntryForKey (o) = null;        } public void Clear () {HashMap.this.clear ();        }} public collection<v> values () {collection<v> vs = values;    return (vs! = null? VS: (values = new values ()));            Private Final class Values extends abstractcollection<v> {public iterator<v> Iterator () {        return Newvalueiterator ();        } public int size () {return size;        Public Boolean contains (Object o) {return containsvalue (o);       } public void Clear () {     HashMap.this.clear ();     }} private transient set<map.entry<k,v>> entryset = null;     /** Note: Here, here, to tell the truth I do not understand, why this kind of writing entryset () re-tune EntrySet0 (). Search the Internet, there is no convincing argument.     If any one knows, be sure to let me know.    */Public set<map.entry<k,v>> EntrySet () {return entrySet0 ();        } private set<map.entry<k,v>> EntrySet0 () {set<map.entry<k,v>> es = EntrySet; return ES! = null?    Es: (entryset = new EntrySet ()); } Private Final class EntrySet extends abstractset<map.entry<k,v>> {public iterator<map.entry&lt ;        K,v>> iterator () {return newentryiterator (); } public boolean contains (Object o) {if (!) (            o instanceof Map.entry)) return false;            Map.entry<k,v> e = (map.entry<k,v>) o;            entry<k,v> candidate = Getentry (E.getkey ());        return candidate! = null && candidate.equals (e);       } public boolean remove (Object o) {return removemapping (o) = null;        } public int size () {return size;        } public void Clear () {HashMap.this.clear (); }    }

Java Note-hashmap

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.