Java Collection-HashTable, java-hashtable
Overview
Like HashMap, Hashtable is also a hash that stores key-value pairs.
Hashtable is defined in Java:
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable
From the source code, we can see that Hashtable inherits from the Dictionary class and implements the Map, Cloneable, and java. io. Serializable interfaces. The Dictionary class is an abstract parent class that maps keys to corresponding values (such as Hashtable). Each key and value is an object.
Member variables
Hashtable is a hash table implemented by the "Zipper method. It includes several important member variables: table, count, threshold, loadFactor, and modCount.
- Table is an Entry [] array type, and Entry (explained in HashMap) is actually a one-way linked list. The "key-value pairs" of the hash table are all stored in the Entry array.
- Count is the size of Hashtable, which is the number of key-value pairs saved by Hashtable.
- Threshold is the Hashtable threshold, used to determine whether to adjust the Hashtable capacity. Value of threshold = "capacity * loading factor ".
- LoadFactor is the load factor.
ModCount is used to implement the fail-fast mechanism.
/** * The hash table data. */ private transient Entry<K,V>[] table; /** * The total number of entries in the hash table. */ private transient int count; /** * The table is rehashed when its size exceeds this threshold. (The * value of this field is (int)(capacity * loadFactor).) * * @serial */ private int threshold; /** * The load factor for the hashtable. * * @serial */ private float loadFactor; /** * The number of times this Hashtable has been structurally modified * Structural modifications are those that change the number of entries in * the Hashtable or otherwise modify its internal structure (e.g., * rehash). This field is used to make iterators on Collection-views of * the Hashtable fail-fast. (See ConcurrentModificationException). */ private transient int modCount = 0;
Constructor
Hashtable provides four constructor methods:
-
public Hashtable(int initialCapacity, float loadFactor): Create a New empty hash table with the specified initial capacity and the specified loading factor. UseAltHashing is boolean. If it is true, another hash string key is executed to reduce hash conflicts caused by weak hash calculation.
public Hashtable(int initialCapacity): Create a New empty hash table with the specified initial capacity and the default load factor (0.75.
public Hashtable(): Default constructor. The capacity is 11 and the load factor is 0.75.
public Hashtable(Map<? extends K, ? extends V> t): Construct a new hash table with the same ing relationship with the given Map.
/** * Constructs a new, empty hashtable with the specified initial * capacity and the specified load factor. * * @param initialCapacity the initial capacity of the hashtable. * @param loadFactor the load factor of the hashtable. * @exception IllegalArgumentException if the initial capacity is less * than zero, or if the load factor is nonpositive. */ 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); useAltHashing = sun.misc.VM.isBooted() && (initialCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD); } /** * Constructs a new, empty hashtable with the specified initial capacity * and default load factor (0.75). * * @param initialCapacity the initial capacity of the hashtable. * @exception IllegalArgumentException if the initial capacity is less * than zero. */ public Hashtable(int initialCapacity) { this(initialCapacity, 0.75f); } /** * Constructs a new, empty hashtable with a default initial capacity (11) * and load factor (0.75). */ public Hashtable() { this(11, 0.75f); } /** * Constructs a new hashtable with the same mappings as the given * Map. The hashtable is created with an initial capacity sufficient to * hold the mappings in the given Map and a default load factor (0.75). * * @param t the map whose mappings are to be placed in this map. * @throws NullPointerException if the specified map is null. * @since 1.2 */ public Hashtable(Map<? extends K, ? extends V> t) { this(Math.max(2*t.size(), 11), 0.75f); putAll(t); }Put Method
The entire process of the put method is:
The following code also provides some comments:
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. // ensure that the key is not in hashtable. // first, calculate the hash value of the key using the hash method, calculate the index value, and determine its position in table []. // second, iterate the linked list at the index position. If the linked list at the position has the same key, replace the value and return the old value Entry tab [] = table; int hash = hash (key); int index = (hash & 0x7FFF FFFF) % tab. length; for (Entry <K, V> e = tab [index]; e! = Null; e = e. next) {if (e. hash = hash) & e. key. equals (key) {V old = e. value; e. value = value; return old ;}} modCount ++; if (count> = threshold) {// Rehash the table if the threshold is exceeded // if the threshold value is exceeded, rehash (); tab = table; hash = hash (key); index = (hash & 0x7fffff) % tab. length;} // Creates the new entry. // Insert the value and return null Entry <K, V> e = tab [index]; // create a new Entry node, insert the new Entry into the index position of Hashtable, and set e to the next element of the new Entry, tab [index] = new Entry <> (hash, key, value, e ); count ++; return null ;}
An example is provided to illustrate the process:
Assume that the Hashtable capacity is 5 and there are five key-value pairs (5, 5), (13, 13), (16, 16), (17, 17), and, their position in Hashtable is as follows:
Now, we insert a new key-value pair, put (16, 22). Assume that the index of key = 16 is 1. but now there are two entries at Index 1, so the program will iterate on the linked list. During iteration, we find that the key of an Entry is the same as the key of the key-value pair we want to insert. So now we will replace newValue = 22 with oldValue = 16, then return oldValue = 16.
Then we insert another put (), key = 33 index is 3, and there is no Entry with key = 33 in the linked list, therefore, insert the node into the first position of the linked list.
Get Method
Compared with the put method, the get method is much simpler. The process is to first obtain the hash value of the key through the hash () method, and then index the key based on the hash value (the algorithms used in the preceding two steps are the same as those used in the put method ). Then, the linked list is iterated to return the corresponding value of the matched key. If no value is found, null is returned.
public synchronized V get(Object key) { Entry tab[] = table; int hash = hash(key); int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { return e.value; } } return null; }Hashtable Traversal
Hashtable has multiple traversal methods:
// 1. Use keys () Enumeration <String> en1 = table. keys (); while (en1.hasMoreElements () {en1.nextElement ();} // 2. Use elements () Enumeration <String> en2 = table. elements (); while (en2.hasMoreElements () {en2.nextElement ();} // 3. Use keySet () Iterator <String> it1 = table. keySet (). iterator (); while (it1.hasNext () {it1.next ();} // 4. Use entrySet () Iterator <Entry <String, String> it2 = table. entrySet (). iterator (); while (it2.hasNext () {it2.next ();}Simple comparison between Hashtable and HashMap