Hashtable of Java source code
1. Hashtable Overview
Class implements a hash table, which maps the key-key object to the corresponding value object. Both key and value are requiredNon-null. To successfully store and obtain objects in a hash table, the hashCode and equals methods must be implemented for the objects used as keys.
Hashtable is thread-synchronized, but non-thread-synchronized HashMap can replace it completely.
If thread security is not required, use HashMap instead;
To ensure thread security and high concurrency, use java. util. concurrent. ConcurrentHashMap instead.
Ii. Hashtable Data Structure
Like HashMap before jdk1.8, Hashtable usesArray + linked list.
/*** Hashtable array conflict link node */private static class Entry
Implements Map. Entry
{Final int hash; final K key; V value; Entry
Next; // The next node protected Entry (int hash, K key, V value, Entry
Next) {this. hash = hash; this. key = key; this. value = value; this. next = next ;}@ SuppressWarnings ("unchecked") protected Object clone () {return new Entry <> (hash, key, value, (next = null? Null: (Entry
) Next. clone ();} // Map. entry Ops public K getKey () {return key;} public V getValue () {return value;} public V setValue (V value) {if (value = null) throw new NullPointerException (); V oldValue = this. value; this. value = value; return oldValue;} public boolean equals (Object o) {if (! (O instanceof Map. Entry) return false; Map. Entry
E = (Map. Entry
) O; return (key = null? E. getKey () = null: key. equals (e. getKey () & (value = null? E. getValue () = null: value. equals (e. getValue ();} public int hashCode () {return hash ^ Objects. hashCode (value);} public String toString () {return key. toString () + "=" + value. toString ();}}
Iii. Hashtable source code
1. header file
package java.util;import java.io.*;import java.util.concurrent.ThreadLocalRandom;import java.util.function.BiConsumer;import java.util.function.Function;import java.util.function.BiFunction;
2. Implementation and inheritance
public class Hashtable
extends Dictionary
implements Map
, Cloneable, java.io.Serializable
3. Attributes
/*** Hash table array */private transient Entry
[] Table;/*** number of elements stored in the array */private transient int count;/*** threshold value, * threshold = capacity * loadFactor */private int threshold;/*** load factor */private float loadFactor; /*** number of modifications * use the fail-fast mechanism */private transient int modCount = 0;
4. constructor and Method
The main difference between this part and HashMap is the hash function algorithm.
Here, we use the typical division of residue method:
int index = (hash & 0x7FFFFFFF) % tab.length;
This part of the constructor and method is not much different from HashMap, but synchronized is added before the method to synchronize the method.
/*** Constructor 1: * use the specified capacity + specified load factor to construct */public Hashtable (int initialCapacity, float loadFactor) {if (initialCapacity <0) throw new IllegalArgumentException ("Illegal Capacity:" + initialCapacity); if (loadFactor <= 0 | Float. isNaN (loadFactor) throw new IllegalArgumentException ("Illegal Load:" + loadFactor); if (initialCapacity = 0) initialCapacity = 1; this. loadFactor = loadFactor; table = new Entry
[InitialCapacity]; threshold = (int) Math. min (initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);}/*** Construction Method 2: * specify capacity + default loading Factor construction */public Hashtable (int initialCapacity) {this (initialCapacity, 0.75f);}/*** constructor 3: * use default capacity 11 + default load factor */public Hashtable () {this (11, 0.75f);}/*** Construction Method 4: * use Map to construct */public Hashtable (Map
T) {this (Math. max (2 * t. size (), 11), 0.75f); putAll (t);}/*** return capacity size */public synchronized int size () {return count ;} /*** empty judge */public synchronized boolean isEmpty () {return count = 0;}/*** returns the Enumeration set of all key values */public synchronized Enumeration
Keys () {return this.
GetEnumeration (KEYS);}/*** returns an Enumeration set of all value values */public synchronized Enumeration
Elements () {return this.
GetEnumeration (VALUES);}/*** determines whether the Object contains the value */public synchronized boolean contains (Object value) {if (value = null) {throw new NullPointerException ();} Entry
Tab [] = table; for (int I = tab. length; I --> 0;) {for (Entry
E = tab [I]; e! = Null; e = e. next) {if (e. value. equals (value) {return true ;}} return false;}/*** determine whether to include the value Object */public boolean containsValue (Object value) {return contains (value);}/*** determines whether the Object contains the key value */public synchronized boolean containsKey (Object key) {Entry
Tab [] = table; int hash = key. hashCode (); int index = (hash & 0x7fffff) % tab. length; for (Entry
E = tab [index]; e! = Null; e = e. next) {if (e. hash = hash) & e. key. equals (key) {return true;} return false;}/*** get the value corresponding to the key value */@ SuppressWarnings ("unchecked ") public synchronized V get (Object key) {Entry
Tab [] = table; int hash = key. hashCode (); int index = (hash & 0x7fffff) % tab. length; for (Entry
E = tab [index]; e! = Null; e = e. next) {if (e. hash = hash) & e. key. equals (key) {return (V) e. value ;}} return null;}/*** maximum array capacity */private static final int MAX_ARRAY_SIZE = Integer. MAX_VALUE-8;/*** resize (2 * oldCap + 1) */@ SuppressWarnings ("unchecked") protected void rehash () {int oldCapacity = table. length; Entry
[] OldMap = table; // overflow-conscious code int newCapacity = (oldCapacity <1) + 1; if (newCapacity-MAX_ARRAY_SIZE> 0) {if (oldCapacity = MAX_ARRAY_SIZE) // Keep running with MAX_ARRAY_SIZE buckets return; newCapacity = MAX_ARRAY_SIZE;} Entry
[] NewMap = new Entry
[NewCapacity]; modCount ++; threshold = (int) Math. min (newCapacity * loadFactor, MAX_ARRAY_SIZE + 1); table = newMap; for (int I = oldCapacity; I --> 0;) {for (Entry
Old = (Entry
) OldMap [I]; old! = Null;) {Entry
E = old; old = old. next; int index = (e. hash & 0x7FFFFFFF) % newCapacity; e. next = (Entry
) NewMap [index]; newMap [index] = e ;}} private void addEntry (int hash, K key, V value, int index) {modCount ++; Entry
Tab [] = table; if (count> = threshold) {// Rehash the table if the threshold is exceeded rehash (); tab = table; hash = key. hashCode (); index = (hash & 0x7FFFFFFF) % tab. length;} // Creates the new entry. @ SuppressWarnings ("unchecked") Entry
E = (Entry
) Tab [index]; tab [index] = new Entry <> (hash, key, value, e); count ++ ;} /***** add element * The original key value exists, and the return value * The original key value does not exist. null */public synchronized V put (K key, V value) {// Make sure the value is not null if (value = null) {throw new NullPointerException ();} // Makes sure the key is not already in the hashtable. entry
Tab [] = table; int hash = key. hashCode (); int index = (hash & 0x7FFFFFFF) % tab. length; @ SuppressWarnings ("unchecked") Entry
Entry = (Entry
) Tab [index]; for (; entry! = Null; entry = entry. next) {if (entry. hash = hash) & entry. key. equals (key) {V old = entry. value; entry. value = value; return old ;}} addEntry (hash, key, value, index); return null ;} /*** Delete and return the value to be deleted */public synchronized V remove (Object key) {Entry
Tab [] = table; int hash = key. hashCode (); int index = (hash & 0x7FFFFFFF) % tab. length; @ SuppressWarnings ("unchecked") Entry
E = (Entry
) Tab [index]; for (Entry
Prev = null; e! = Null; prev = e, e = e. next) {if (e. hash = hash) & e. key. equals (key) {modCount ++; if (prev! = Null) {prev. next = e. next;} else {tab [index] = e. next;} count --; V oldValue = e. value; e. value = null; return oldValue;} return null;}/*** Add the elements in the Map */public synchronized void putAll (Map
T) {for (Map. Entry
E: t. entrySet () put (e. getKey (), e. getValue ();}/*** clear */public synchronized void clear () {Entry
Tab [] = table; modCount ++; for (int index = tab. length; -- index> = 0;) tab [index] = null; count = 0;}/*** clone Object */public synchronized Object clone () {try {Hashtable
T = (Hashtable
) Super. clone (); t. table = new Entry
[Table. length]; for (int I = table. length; I --> 0;) {t. table [I] = (table [I]! = Null )? (Entry
) Table [I]. clone (): null;} t. keySet = null; t. entrySet = null; t. values = null; t. modCount = 0; return t;} catch (CloneNotSupportedException e) {// this shouldn't happen, since we are Cloneable throw new InternalError (e);} private
Enumeration
GetEnumeration (int type) {if (count = 0) {return Collections. emptyEnumeration ();} else {return new Enumerator <> (type, false);} // obtain the iterator private
Iterator
GetIterator (int type) {if (count = 0) {return Collections. emptyIterator ();} else {return new Enumerator <> (type, true );}} // Views/*** Each of these fields are initialized to contain an instance of the * appropriate view the first time this view is requested. the views are * stateless, so there's no reason to create more than one of each. */private transient volatile Set
KeySet; private transient volatile Set
> EntrySet; private transient volatile Collection
Values;/*** return the Set view containing the map * Get the Iterator object through the Set view and iterate over the map */public Set
> EntrySet () {if (entrySet = null) entrySet = Collections. synchronizedSet (new EntrySet (), this); return entrySet;} // Set View class private class EntrySet extends actset
> {Public Iterator
> Iterator () {return getIterator (ENTRIES);} public boolean add (Map. Entry
O) {return super. add (o);} public boolean contains (Object o) {if (! (O instanceof Map. Entry) return false; Map. Entry
Entry = (Map. Entry
) O; Object key = entry. getKey (); Entry
[] Tab = table; int hash = key. hashCode (); int index = (hash & 0x7fffff) % tab. length; for (Entry
E = tab [index]; e! = Null; e = e. next) if (e. hash = hash & e. equals (entry) return true; return false;} public boolean remove (Object o) {if (! (O instanceof Map. Entry) return false; Map. Entry
Entry = (Map. Entry
) O; Object key = entry. getKey (); Entry
[] Tab = table; int hash = key. hashCode (); int index = (hash & 0x7FFFFFFF) % tab. length; @ SuppressWarnings ("unchecked") Entry
E = (Entry
) Tab [index]; for (Entry
Prev = null; e! = Null; prev = e, e = e. next) {if (e. hash = hash & e. equals (entry) {modCount ++; if (prev! = Null) prev. next = e. next; else tab [index] = e. next; count --; e. value = null; return true;} return false;} public int size () {return count;} public void clear () {Hashtable. this. clear () ;}/ *** Returns a {@ link Collection} view of the values contained in this map. * The collection is backed by the map, so changes to the map are * reflected in the collection, and vice-versa. if the map is * modified while an iteration over the collection is in progress * (could t through the iterator's own
RemoveOperation), * the results of the iteration are undefined. The collection * supports element removal, which removes the corresponding * mapping from the map, via
Iterator. remove,*
Collection. remove,
RemoveAll,*
RetainAllAnd
ClearOperations. It does not * support
AddOr
AddAllOperations. ** @ since 1.2 */public Collection
Values () {if (values = null) values = Collections. synchronizedCollection (new ValueCollection (), this); return values;} private class ValueCollection extends AbstractCollection
{Public Iterator
Iterator () {return getIterator (VALUES);} public int size () {return count;} public boolean contains (Object o) {return containsValue (o );} public void clear () {Hashtable. this. clear () ;}// Comparison and hashing/*** implement equals * judgment and so on */public synchronized boolean equals (Object o) {if (o = this) return true; if (! (O instanceof Map) return false; Map
T = (Map
) O; if (t. size ()! = Size () return false; try {Iterator
> I = entrySet (). iterator (); while (I. hasNext () {Map. Entry
E = I. next (); K key = e. getKey (); V value = e. getValue (); if (value = null) {if (! (T. get (key) = null & t. containsKey (key) return false;} else {if (! Value. equals (t. get (key) return false ;}} catch (ClassCastException unused) {return false;} catch (NullPointerException unused) {return false;} return true ;} /*** implement hashCode */public synchronized int hashCode () {/** This code detects the recursion caused by computing the hash code * of a self-referential hash table and prevents the stack overflow * that wowould otherwise result. this allows certain 1.1-era * applets with self-referential hash tables to work. this code * abuses the loadFactor field to do double-duty as a hashCode * in progress flag, so as not to worsen the space performance. * A negative load factor indicates that hash code computation is * in progress. */int h = 0; if (count = 0 | loadFactor <0) return h; // Returns zero loadFactor =-loadFactor; // Mark hashCode computation in progress Entry
[] Tab = table; for (Entry
Entry: tab) {while (entry! = Null) {h + = entry. hashCode (); entry = entry. next ;}} loadFactor =-loadFactor; // Mark hashCode computation complete return h;} @ Overridepublic synchronized boolean replace (K key, V oldValue, V newValue) {Objects. requireNonNull (oldValue); Objects. requireNonNull (newValue); Entry
Tab [] = table; int hash = key. hashCode (); int index = (hash & 0x7FFFFFFF) % tab. length; @ SuppressWarnings ("unchecked") Entry
E = (Entry
) Tab [index]; for (; e! = Null; e = e. next) {if (e. hash = hash) & e. key. equals (key) {if (e. value. equals (oldValue) {e. value = newValue; return true;} else {return false ;}} return false;}/** replace */@ Overridepublic synchronized V replace (K key, V value) {Objects. requireNonNull (value); Entry
Tab [] = table; int hash = key. hashCode (); int index = (hash & 0x7FFFFFFF) % tab. length; @ SuppressWarnings ("unchecked") Entry
E = (Entry
) Tab [index]; for (; e! = Null; e = e. next) {if (e. hash = hash) & e. key. equals (key) {V oldValue = e. value; e. value = value; return oldValue;} return null ;}